From 5ecd1c965571c3df2fb3295994acfe9b557a7f1c Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 19 Jun 2013 12:15:50 +0200 Subject: [PATCH 001/265] 8016476: PPC64 (part 1): reenable CORE build Reenable CORE build on PPC64 Reviewed-by: dholmes, kvn, coleenp --- hotspot/make/Makefile | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 526ed2393f2..3959d280346 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -87,6 +87,7 @@ endif # Typical C1/C2 targets made available with this Makefile C1_VM_TARGETS=product1 fastdebug1 optimized1 debug1 C2_VM_TARGETS=product fastdebug optimized debug +CORE_VM_TARGETS=productcore fastdebugcore optimizedcore debugcore ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero debugzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark debugshark MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 debugminimal1 @@ -136,6 +137,12 @@ all_fastdebugshark: fastdebugshark docs export_fastdebug all_debugshark: debugshark docs export_debug all_optimizedshark: optimizedshark docs export_optimized +allcore: all_productcore all_fastdebugcore +all_productcore: productcore docs export_product +all_fastdebugcore: fastdebugcore docs export_fastdebug +all_debugcore: debugcore docs export_debug +all_optimizedcore: optimizedcore docs export_optimized + # Do everything world: all create_jdk @@ -154,6 +161,7 @@ endif # Output directories C1_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 C2_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 +CORE_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_core MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 ZERO_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_zero SHARK_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_shark @@ -167,6 +175,10 @@ $(C2_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_DIR=$(C2_DIR) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) +$(CORE_VM_TARGETS): + $(CD) $(GAMMADIR)/make; \ + $(MAKE) BUILD_DIR=$(CORE_DIR) BUILD_FLAVOR=$(@:$core=%) VM_TARGET=$@ generic_buildcore $(ALT_OUT) + $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_DIR=$(ZERO_DIR) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ generic_buildzero $(ALT_OUT) @@ -228,6 +240,20 @@ else $(MAKE_ARGS) $(VM_TARGET) endif +generic_buildcore: $(HOTSPOT_SCRIPT) +ifeq ($(HS_ARCH),ppc) + ifeq ($(ARCH_DATA_MODEL),64) + $(MKDIR) -p $(OUTPUTDIR) + $(CD) $(OUTPUTDIR); \ + $(MAKE) -f $(ABS_OS_MAKEFILE) \ + $(MAKE_ARGS) $(VM_TARGET) + else + @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" + endif +else + @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" +endif + generic_buildzero: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ @@ -287,6 +313,7 @@ XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs C1_BUILD_DIR =$(C1_DIR)/$(BUILD_FLAVOR) C2_BUILD_DIR =$(C2_DIR)/$(BUILD_FLAVOR) +CORE_BUILD_DIR =$(CORE_DIR)/$(BUILD_FLAVOR) MINIMAL1_BUILD_DIR=$(MINIMAL1_DIR)/$(BUILD_FLAVOR) ZERO_BUILD_DIR =$(ZERO_DIR)/$(BUILD_FLAVOR) SHARK_BUILD_DIR =$(SHARK_DIR)/$(BUILD_FLAVOR) @@ -448,6 +475,28 @@ $(EXPORT_SERVER_DIR)/%.diz: $(ZERO_BUILD_DIR)/%.diz $(install-file) endif +# Core +ifeq ($(JVM_VARIANT_CORE), true) +# Common +$(EXPORT_LIB_DIR)/%.jar: $(CORE_DIR)/../generated/%.jar + $(install-file) +$(EXPORT_INCLUDE_DIR)/%: $(CORE_DIR)/../generated/jvmtifiles/% + $(install-file) +# Unix +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(CORE_DIR)/%.debuginfo + $(install-file) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(CORE_DIR)/%.diz + $(install-file) +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) +$(EXPORT_SERVER_DIR)/%.debuginfo: $(CORE_DIR)/%.debuginfo + $(install-file) +$(EXPORT_SERVER_DIR)/%.diz: $(CORE_DIR)/%.diz + $(install-file) +endif + # Shark ifeq ($(JVM_VARIANT_ZEROSHARK), true) # Common @@ -510,6 +559,7 @@ clobber clean: clean_build clean_export clean_jdk clean_build: $(RM) -r $(C1_DIR) $(RM) -r $(C2_DIR) + $(RM) -r $(CORE_DIR) $(RM) -r $(ZERO_DIR) $(RM) -r $(SHARK_DIR) $(RM) -r $(MINIMAL1_DIR) From 036382cefdddc53a2161ee77ddf9ab677e28c4c7 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 19 Jun 2013 12:29:30 +0200 Subject: [PATCH 002/265] 8016491: PPC64 (part 2): Clean up PPC defines Distinguish PPC, PPC64 and PPC32. PPC should guard code needed on any PPC system. PPC32 and PPC64 should guard code needed in a port for the ppc64 or ppc32 instruction set. Reviewed-by: kvn --- hotspot/make/linux/platform_ppc | 2 +- hotspot/src/os/bsd/vm/os_bsd.cpp | 2 +- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- .../src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp | 2 +- .../os_cpu/linux_zero/vm/os_linux_zero.hpp | 2 +- hotspot/src/share/vm/runtime/frame.cpp | 6 ++--- hotspot/src/share/vm/runtime/frame.hpp | 2 +- .../src/share/vm/runtime/sharedRuntime.cpp | 2 +- .../src/share/vm/runtime/sharedRuntime.hpp | 2 +- hotspot/src/share/vm/runtime/vm_version.cpp | 4 ++-- hotspot/src/share/vm/utilities/macros.hpp | 22 ++++++++++++++++++- 11 files changed, 34 insertions(+), 14 deletions(-) diff --git a/hotspot/make/linux/platform_ppc b/hotspot/make/linux/platform_ppc index c37b8d6b12c..6e223c00e52 100644 --- a/hotspot/make/linux/platform_ppc +++ b/hotspot/make/linux/platform_ppc @@ -14,4 +14,4 @@ compiler = gcc gnu_dis_arch = ppc -sysdefs = -DLINUX -D_GNU_SOURCE -DPPC +sysdefs = -DLINUX -D_GNU_SOURCE -DPPC32 diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index f0b32196f5d..63525e37f3b 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -205,7 +205,7 @@ static char cpu_arch[] = "i386"; static char cpu_arch[] = "amd64"; #elif defined(ARM) static char cpu_arch[] = "arm"; -#elif defined(PPC) +#elif defined(PPC32) static char cpu_arch[] = "ppc"; #elif defined(SPARC) # ifdef _LP64 diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 4ca47019569..8c406f2e732 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -247,7 +247,7 @@ static char cpu_arch[] = "i386"; static char cpu_arch[] = "amd64"; #elif defined(ARM) static char cpu_arch[] = "arm"; -#elif defined(PPC) +#elif defined(PPC32) static char cpu_arch[] = "ppc"; #elif defined(SPARC) # ifdef _LP64 diff --git a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp index 873e598aba9..aaccdcb19d5 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp @@ -36,7 +36,7 @@ // Atomically copy 64 bits of data static void atomic_copy64(volatile void *src, volatile void *dst) { -#if defined(PPC) && !defined(_LP64) +#if defined(PPC32) double tmp; asm volatile ("lfd %0, 0(%1)\n" "stfd %0, 0(%2)\n" diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp index 1d4576679d3..7b7e367ed37 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp @@ -36,7 +36,7 @@ // Atomically copy 64 bits of data static void atomic_copy64(volatile void *src, volatile void *dst) { -#if defined(PPC) && !defined(_LP64) +#if defined(PPC32) double tmp; asm volatile ("lfd %0, 0(%1)\n" "stfd %0, 0(%2)\n" diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index e1913829702..f1a477aefda 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -918,7 +918,7 @@ void frame::oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f, cld_f->do_cld(m->method_holder()->class_loader_data()); } -#if !defined(PPC) || defined(ZERO) +#if !defined(PPC32) || defined(ZERO) if (m->is_native()) { #ifdef CC_INTERP interpreterState istate = get_interpreterState(); @@ -927,11 +927,11 @@ void frame::oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f, f->do_oop((oop*)( fp() + interpreter_frame_oop_temp_offset )); #endif /* CC_INTERP */ } -#else // PPC +#else // PPC32 if (m->is_native() && m->is_static()) { f->do_oop(interpreter_frame_mirror_addr()); } -#endif // PPC +#endif // PPC32 int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals(); diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 2e27430f7fb..c0da50cb2bb 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -346,7 +346,7 @@ class frame VALUE_OBJ_CLASS_SPEC { void interpreter_frame_set_method(Method* method); Method** interpreter_frame_method_addr() const; ConstantPoolCache** interpreter_frame_cache_addr() const; -#ifdef PPC +#ifdef PPC32 oop* interpreter_frame_mirror_addr() const; #endif diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 114f27d20a8..99afd4d6927 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -406,7 +406,7 @@ double SharedRuntime::dabs(double f) { #endif -#if defined(__SOFTFP__) || defined(PPC) +#if defined(__SOFTFP__) || defined(PPC32) double SharedRuntime::dsqrt(double f) { return sqrt(f); } diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index e6867645ae6..5902d3b2830 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -140,7 +140,7 @@ class SharedRuntime: AllStatic { static double dabs(double f); #endif -#if defined(__SOFTFP__) || defined(PPC) +#if defined(__SOFTFP__) || defined(PPC32) static double dsqrt(double f); #endif diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 322a5b6c03a..04b2e1e18cc 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -186,7 +186,7 @@ const char* Abstract_VM_Version::jre_release_version() { IA64_ONLY("ia64") \ AMD64_ONLY("amd64") \ ARM_ONLY("arm") \ - PPC_ONLY("ppc") \ + PPC32_ONLY("ppc") \ SPARC_ONLY("sparc") #endif // ZERO @@ -248,7 +248,7 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #define FLOAT_ARCH_STR "-e500v2" #elif defined(ARM) #define FLOAT_ARCH_STR "-vfp" - #elif defined(PPC) + #elif defined(PPC32) #define FLOAT_ARCH_STR "-hflt" #else #define FLOAT_ARCH_STR "" diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index a97e9e7d039..27782beb1f4 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -340,14 +340,34 @@ #define NOT_SPARC(code) code #endif -#ifdef PPC +#if defined(PPC32) || defined(PPC64) +#ifndef PPC +#define PPC +#endif #define PPC_ONLY(code) code #define NOT_PPC(code) #else +#undef PPC #define PPC_ONLY(code) #define NOT_PPC(code) code #endif +#ifdef PPC32 +#define PPC32_ONLY(code) code +#define NOT_PPC32(code) +#else +#define PPC32_ONLY(code) +#define NOT_PPC32(code) code +#endif + +#ifdef PPC64 +#define PPC64_ONLY(code) code +#define NOT_PPC64(code) +#else +#define PPC64_ONLY(code) +#define NOT_PPC64(code) code +#endif + #ifdef E500V2 #define E500V2_ONLY(code) code #define NOT_E500V2(code) From 0522ce7a17e3fc3187cacf2ca07c254a363244ab Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 20 Jun 2013 16:30:44 -0700 Subject: [PATCH 003/265] 8016586: PPC64 (part 3): basic changes for PPC64 Added #includes needed for ppc64 port. Renamed _MODEL_ppc to _MODEL_ppc_32 and renamed corresponding old _ppc files to _ppc_32. Reviewed-by: dholmes, kvn --- hotspot/agent/src/os/linux/libproc.h | 2 +- hotspot/make/linux/platform_ppc | 4 ++-- hotspot/src/os/linux/vm/os_linux.cpp | 9 +++++---- hotspot/src/share/vm/adlc/main.cpp | 5 +++++ hotspot/src/share/vm/code/vmreg.hpp | 7 +++++-- hotspot/src/share/vm/compiler/compileBroker.cpp | 2 +- .../gc_implementation/g1/g1OopClosures.inline.hpp | 1 + .../parallelScavenge/psPromotionManager.inline.hpp | 1 + .../share/vm/interpreter/abstractInterpreter.hpp | 7 +++++-- hotspot/src/share/vm/interpreter/templateTable.hpp | 11 +++++++---- hotspot/src/share/vm/opto/c2_globals.hpp | 3 +++ hotspot/src/share/vm/opto/c2compiler.cpp | 7 +++++-- hotspot/src/share/vm/opto/compile.cpp | 7 +++++-- hotspot/src/share/vm/opto/gcm.cpp | 8 ++++++-- hotspot/src/share/vm/opto/lcm.cpp | 7 +++++-- hotspot/src/share/vm/opto/locknode.hpp | 7 +++++-- hotspot/src/share/vm/opto/matcher.cpp | 7 +++++-- hotspot/src/share/vm/opto/output.hpp | 7 +++++-- hotspot/src/share/vm/opto/regmask.cpp | 7 +++++-- hotspot/src/share/vm/opto/regmask.hpp | 7 +++++-- hotspot/src/share/vm/opto/runtime.cpp | 13 ++++++++----- hotspot/src/share/vm/runtime/deoptimization.cpp | 7 +++++-- hotspot/src/share/vm/runtime/frame.hpp | 7 +++++-- hotspot/src/share/vm/runtime/globals.hpp | 6 +++--- hotspot/src/share/vm/runtime/stubRoutines.hpp | 7 +++++-- hotspot/src/share/vm/runtime/vmStructs.cpp | 7 +++++-- hotspot/src/share/vm/runtime/vm_version.cpp | 1 + 27 files changed, 114 insertions(+), 50 deletions(-) diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index 4cde0c19d76..5da6c6928f0 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -80,7 +80,7 @@ combination of ptrace and /proc calls. *************************************************************************************/ -#if defined(sparc) || defined(sparcv9) +#if defined(sparc) || defined(sparcv9) || defined(ppc64) #define user_regs_struct pt_regs #endif diff --git a/hotspot/make/linux/platform_ppc b/hotspot/make/linux/platform_ppc index 6e223c00e52..809456b526b 100644 --- a/hotspot/make/linux/platform_ppc +++ b/hotspot/make/linux/platform_ppc @@ -2,11 +2,11 @@ os_family = linux arch = ppc -arch_model = ppc +arch_model = ppc_32 os_arch = linux_ppc -os_arch_model = linux_ppc +os_arch_model = linux_ppc_32 lib_arch = ppc diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 8c406f2e732..eefd5ef0384 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -132,7 +132,7 @@ static int clock_tics_per_sec = 100; // For diagnostics to print a message once. see run_periodic_checks static sigset_t check_signal_done; -static bool check_signals = true;; +static bool check_signals = true; static pid_t _initial_pid = 0; @@ -249,6 +249,8 @@ static char cpu_arch[] = "amd64"; static char cpu_arch[] = "arm"; #elif defined(PPC32) static char cpu_arch[] = "ppc"; +#elif defined(PPC64) +static char cpu_arch[] = "ppc64"; #elif defined(SPARC) # ifdef _LP64 static char cpu_arch[] = "sparcv9"; @@ -4402,7 +4404,7 @@ jint os::init_2(void) // the future if the appropriate cleanup code can be added to the // VM_Exit VMOperation's doit method. if (atexit(perfMemory_exit_helper) != 0) { - warning("os::init2 atexit(perfMemory_exit_helper) failed"); + warning("os::init_2 atexit(perfMemory_exit_helper) failed"); } } @@ -4413,8 +4415,7 @@ jint os::init_2(void) } // this is called at the end of vm_initialization -void os::init_3(void) -{ +void os::init_3(void) { #ifdef JAVASE_EMBEDDED // Start the MemNotifyThread if (LowMemoryProtection) { diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index 4b812316381..2edcb095c9c 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.cpp @@ -242,6 +242,11 @@ int main(int argc, char *argv[]) #ifdef TARGET_ARCH_arm AD.addInclude(AD._CPP_file, "nativeInst_arm.hpp"); AD.addInclude(AD._CPP_file, "vmreg_arm.inline.hpp"); +#endif +#ifdef TARGET_ARCH_ppc + AD.addInclude(AD._CPP_file, "assembler_ppc.inline.hpp"); + AD.addInclude(AD._CPP_file, "nativeInst_ppc.hpp"); + AD.addInclude(AD._CPP_file, "vmreg_ppc.inline.hpp"); #endif AD.addInclude(AD._HPP_file, "memory/allocation.hpp"); AD.addInclude(AD._HPP_file, "opto/machnode.hpp"); diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index 70b476de00e..dfb957ba535 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -47,8 +47,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/adGlobals_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/adGlobals_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/adGlobals_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/adGlobals_ppc_64.hpp" #endif #endif diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index ad097d96a9b..7934d2df9db 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -958,7 +958,7 @@ CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQue // Initialize the compilation queue void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; -#if !defined(ZERO) && !defined(SHARK) +#if !defined(ZERO) && !defined(SHARK) && !defined(PPC64) assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); #endif // !ZERO && !SHARK if (c2_compiler_count > 0) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index e26d2a6951d..ccb627c6ed7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -29,6 +29,7 @@ #include "gc_implementation/g1/g1CollectedHeap.hpp" #include "gc_implementation/g1/g1OopClosures.hpp" #include "gc_implementation/g1/g1RemSet.hpp" +#include "gc_implementation/g1/g1RemSet.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" /* diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp index 8822a481b3d..b01fa803d0f 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp @@ -28,6 +28,7 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" +#include "oops/oop.psgc.inline.hpp" inline PSPromotionManager* PSPromotionManager::manager_array(int index) { assert(_manager_array != NULL, "access of NULL manager_array"); diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 264d4fffbf6..aadabdd2676 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -45,8 +45,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "interp_masm_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "interp_masm_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "interp_masm_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "interp_masm_ppc_64.hpp" #endif // This file contains the platform-independent parts diff --git a/hotspot/src/share/vm/interpreter/templateTable.hpp b/hotspot/src/share/vm/interpreter/templateTable.hpp index 40d05f49b49..11b72bb3bba 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.hpp +++ b/hotspot/src/share/vm/interpreter/templateTable.hpp @@ -43,8 +43,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "interp_masm_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "interp_masm_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "interp_masm_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "interp_masm_ppc_64.hpp" #endif #ifndef CC_INTERP @@ -373,8 +376,8 @@ class TemplateTable: AllStatic { #ifdef TARGET_ARCH_MODEL_arm # include "templateTable_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "templateTable_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "templateTable_ppc_32.hpp" #endif }; diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 49ed1e8bcf0..530b8fe7d42 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -35,6 +35,9 @@ #ifdef TARGET_ARCH_arm # include "c2_globals_arm.hpp" #endif +#ifdef TARGET_ARCH_ppc +# include "c2_globals_ppc.hpp" +#endif #ifdef TARGET_OS_FAMILY_linux # include "c2_globals_linux.hpp" #endif diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 85f30a5ac1e..c3db9ca5ffa 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -40,8 +40,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 3222e2596e9..ac22959ed86 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -79,8 +79,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index 811dc5c6c87..5a1cbca63b5 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -50,9 +50,13 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" +#endif + // Portions of code courtesy of Clifford Click diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 2b3eca478d9..c05c054fccb 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -45,8 +45,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif // Optimization - Graph Style diff --git a/hotspot/src/share/vm/opto/locknode.hpp b/hotspot/src/share/vm/opto/locknode.hpp index b11486590a9..d8c400c1e61 100644 --- a/hotspot/src/share/vm/opto/locknode.hpp +++ b/hotspot/src/share/vm/opto/locknode.hpp @@ -43,8 +43,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif //------------------------------BoxLockNode------------------------------------ diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index ffd3cc28346..54df969d7f2 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -53,8 +53,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif OptoReg::Name OptoReg::c_frame_pointer; diff --git a/hotspot/src/share/vm/opto/output.hpp b/hotspot/src/share/vm/opto/output.hpp index 50b6e76035e..498d914f170 100644 --- a/hotspot/src/share/vm/opto/output.hpp +++ b/hotspot/src/share/vm/opto/output.hpp @@ -42,8 +42,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif class Arena; diff --git a/hotspot/src/share/vm/opto/regmask.cpp b/hotspot/src/share/vm/opto/regmask.cpp index 9e9bac6f7e8..07fddd151c3 100644 --- a/hotspot/src/share/vm/opto/regmask.cpp +++ b/hotspot/src/share/vm/opto/regmask.cpp @@ -40,8 +40,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif #define RM_SIZE _RM_SIZE /* a constant private to the class RegMask */ diff --git a/hotspot/src/share/vm/opto/regmask.hpp b/hotspot/src/share/vm/opto/regmask.hpp index 7171ceb8c42..2ea6dfffdd3 100644 --- a/hotspot/src/share/vm/opto/regmask.hpp +++ b/hotspot/src/share/vm/opto/regmask.hpp @@ -43,8 +43,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/adGlobals_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/adGlobals_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/adGlobals_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/adGlobals_ppc_64.hpp" #endif // Some fun naming (textual) substitutions: diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index d0aefad66b7..731178de91a 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -83,8 +83,11 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif @@ -977,7 +980,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t nm = CodeCache::find_nmethod(pc); assert(nm != NULL, "No NMethod found"); if (nm->is_native_method()) { - fatal("Native mathod should not have path to exception handling"); + fatal("Native method should not have path to exception handling"); } else { // we are switching to old paradigm: search for exception handler in caller_frame // instead in exception handler of caller_frame.sender() @@ -1006,7 +1009,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t } // If we are forcing an unwind because of stack overflow then deopt is - // irrelevant sice we are throwing the frame away anyway. + // irrelevant since we are throwing the frame away anyway. if (deopting && !force_unwind) { handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); @@ -1049,7 +1052,7 @@ JRT_END // Note we enter without the usual JRT wrapper. We will call a helper routine that // will do the normal VM entry. We do it this way so that we can see if the nmethod // we looked up the handler for has been deoptimized in the meantime. If it has been -// we must not use the handler and instread return the deopt blob. +// we must not use the handler and instead return the deopt blob. address OptoRuntime::handle_exception_C(JavaThread* thread) { // // We are in Java not VM and in debug mode we have a NoHandleMark diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 4a8d52b1284..c70c5589a7d 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -81,10 +81,13 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/ad_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/ad_ppc_32.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/ad_ppc_64.hpp" #endif +#endif // COMPILER2 bool DeoptimizationMarker::_is_active = false; diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index c0da50cb2bb..e595a9b1d59 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -46,10 +46,13 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/adGlobals_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/adGlobals_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/adGlobals_ppc_32.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/adGlobals_ppc_64.hpp" #endif +#endif // COMPILER2 #ifdef ZERO #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index aec1736a43c..a28b1717d6d 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -167,7 +167,6 @@ define_pd_global(intx, BackEdgeThreshold, 0); define_pd_global(intx, OnStackReplacePercentage, 0); define_pd_global(bool, ResizeTLAB, false); define_pd_global(intx, FreqInlineSize, 0); -define_pd_global(intx, InlineSmallCode, 0); define_pd_global(intx, NewSizeThreadIncrease, 4*K); define_pd_global(intx, InlineClassNatives, true); define_pd_global(intx, InlineUnsafeOps, true); @@ -3143,7 +3142,8 @@ class CommandLineFlags { "disable this feature") \ \ /* code cache parameters */ \ - develop(uintx, CodeCacheSegmentSize, 64, \ + /* ppc64 has large code-entry alignment. */ \ + develop(uintx, CodeCacheSegmentSize, 64 PPC64_ONLY(+64), \ "Code cache segment size (in bytes) - smallest unit of " \ "allocation") \ \ @@ -3605,7 +3605,7 @@ class CommandLineFlags { NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \ "Address to allocate shared memory region for class data") \ \ - diagnostic(bool, EnableInvokeDynamic, true, \ + diagnostic(bool, EnableInvokeDynamic, true PPC64_ONLY(&& false), \ "support JSR 292 (method handles, invokedynamic, " \ "anonymous classes") \ \ diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 91f273e6515..2cb39ec2461 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -114,8 +114,11 @@ class StubRoutines: AllStatic { #ifdef TARGET_ARCH_MODEL_arm # include "stubRoutines_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "stubRoutines_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "stubRoutines_ppc_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "stubRoutines_ppc_64.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index b3fdd1e7097..9dff5e313c2 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -197,10 +197,13 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/adGlobals_arm.hpp" #endif -#ifdef TARGET_ARCH_MODEL_ppc -# include "adfiles/adGlobals_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "adfiles/adGlobals_ppc_32.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "adfiles/adGlobals_ppc_64.hpp" #endif +#endif // COMPILER2 // Note: the cross-product of (c1, c2, product, nonproduct, ...), // (nonstatic, static), and (unchecked, checked) has not been taken. diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 04b2e1e18cc..e7d082d9f61 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -187,6 +187,7 @@ const char* Abstract_VM_Version::jre_release_version() { AMD64_ONLY("amd64") \ ARM_ONLY("arm") \ PPC32_ONLY("ppc") \ + PPC64_ONLY("ppc64") \ SPARC_ONLY("sparc") #endif // ZERO From ac0c6f1e84b3becc7ecb2b8763b7f899d7a06f3e Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 24 Jun 2013 17:11:47 +0200 Subject: [PATCH 004/265] 8017313: PPC64 (part 6): stack handling improvements Precompute limit for stack overflow check. Reviewed-by: kvn, coleenp --- hotspot/src/share/vm/runtime/thread.cpp | 3 +++ hotspot/src/share/vm/runtime/thread.hpp | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 79642c2e4a9..de0aec8f297 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -312,6 +312,9 @@ void Thread::initialize_thread_local_storage() { void Thread::record_stack_base_and_size() { set_stack_base(os::current_stack_base()); set_stack_size(os::current_stack_size()); + if (is_Java_thread()) { + ((JavaThread*) this)->set_stack_overflow_limit(); + } // CR 7190089: on Solaris, primordial thread's stack is adjusted // in initialize_thread(). Without the adjustment, stack size is // incorrect if stack is set to unlimited (ulimit -s unlimited). diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 8b8e6dd4e62..0c9a8579ace 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -893,7 +893,11 @@ class JavaThread: public Thread { private: - StackGuardState _stack_guard_state; + StackGuardState _stack_guard_state; + + // Precompute the limit of the stack as used in stack overflow checks. + // We load it from here to simplify the stack overflow check in assembly. + address _stack_overflow_limit; // Compiler exception handling (NOTE: The _exception_oop is *NOT* the same as _pending_exception. It is // used to temp. parsing values into and out of the runtime system during exception handling for compiled @@ -1301,6 +1305,14 @@ class JavaThread: public Thread { // and reguard if possible. bool reguard_stack(void); + address stack_overflow_limit() { return _stack_overflow_limit; } + void set_stack_overflow_limit() { + _stack_overflow_limit = _stack_base - _stack_size + + ((StackShadowPages + + StackYellowPages + + StackRedPages) * os::vm_page_size()); + } + // Misc. accessors/mutators void set_do_not_unlock(void) { _do_not_unlock_if_synchronized = true; } void clr_do_not_unlock(void) { _do_not_unlock_if_synchronized = false; } @@ -1335,6 +1347,7 @@ class JavaThread: public Thread { static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop ); } static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } + static ByteSize stack_overflow_limit_offset() { return byte_offset_of(JavaThread, _stack_overflow_limit); } static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } From 1e0a3218952b40a10081a8439718015ba64c975e Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 26 Jun 2013 16:06:38 +0200 Subject: [PATCH 005/265] 8017317: PPC64 (part 7): cppInterpreter: implement support for biased locking Reviewed-by: kvn, dholmes --- .../vm/interpreter/bytecodeInterpreter.cpp | 442 ++++++++++++------ 1 file changed, 295 insertions(+), 147 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 8f0ec849cca..c4721bffacd 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -36,6 +36,7 @@ #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" +#include "runtime/biasedLocking.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.hpp" @@ -679,114 +680,97 @@ BytecodeInterpreter::run(interpreterState istate) { // lock method if synchronized if (METHOD->is_synchronized()) { - // oop rcvr = locals[0].j.r; - oop rcvr; - if (METHOD->is_static()) { - rcvr = METHOD->constants()->pool_holder()->java_mirror(); - } else { - rcvr = LOCALS_OBJECT(0); - VERIFY_OOP(rcvr); - } - // The initial monitor is ours for the taking - BasicObjectLock* mon = &istate->monitor_base()[-1]; - oop monobj = mon->obj(); - assert(mon->obj() == rcvr, "method monitor mis-initialized"); + // oop rcvr = locals[0].j.r; + oop rcvr; + if (METHOD->is_static()) { + rcvr = METHOD->constants()->pool_holder()->java_mirror(); + } else { + rcvr = LOCALS_OBJECT(0); + VERIFY_OOP(rcvr); + } + // The initial monitor is ours for the taking + // Monitor not filled in frame manager any longer as this caused race condition with biased locking. + BasicObjectLock* mon = &istate->monitor_base()[-1]; + mon->set_obj(rcvr); + bool success = false; + uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; + markOop mark = rcvr->mark(); + intptr_t hash = (intptr_t) markOopDesc::no_hash; + // Implies UseBiasedLocking. + if (mark->has_bias_pattern()) { + uintptr_t thread_ident; + uintptr_t anticipated_bias_locking_value; + thread_ident = (uintptr_t)istate->thread(); + anticipated_bias_locking_value = + (((uintptr_t)rcvr->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & + ~((uintptr_t) markOopDesc::age_mask_in_place); - bool success = UseBiasedLocking; - if (UseBiasedLocking) { - markOop mark = rcvr->mark(); - if (mark->has_bias_pattern()) { - // The bias pattern is present in the object's header. Need to check - // whether the bias owner and the epoch are both still current. - intptr_t xx = ((intptr_t) THREAD) ^ (intptr_t) mark; - xx = (intptr_t) rcvr->klass()->prototype_header() ^ xx; - intptr_t yy = (xx & ~((int) markOopDesc::age_mask_in_place)); - if (yy != 0 ) { - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - - if (yy & markOopDesc::biased_lock_mask_in_place == 0 ) { - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - if (yy & markOopDesc::epoch_mask_in_place == 0) { - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - intptr_t unbiased = (intptr_t) mark & (markOopDesc::biased_lock_mask_in_place | - markOopDesc::age_mask_in_place | - markOopDesc::epoch_mask_in_place); - if (Atomic::cmpxchg_ptr((intptr_t)THREAD | unbiased, (intptr_t*) rcvr->mark_addr(), unbiased) != unbiased) { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); - } - } else { - try_rebias: - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD; - if (Atomic::cmpxchg_ptr((intptr_t)THREAD | (intptr_t) rcvr->klass()->prototype_header(), - (intptr_t*) rcvr->mark_addr(), - (intptr_t) mark) != (intptr_t) mark) { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); - } - } - } else { - try_revoke_bias: - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD; - if (Atomic::cmpxchg_ptr(rcvr->klass()->prototype_header(), - (intptr_t*) rcvr->mark_addr(), - mark) == mark) { - // (*counters->revoked_lock_entry_count_addr())++; - success = false; - } - } + if (anticipated_bias_locking_value == 0) { + // Already biased towards this thread, nothing to do. + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::biased_lock_entry_count_addr())++; + } + success = true; + } else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { + // Try to revoke bias. + markOop header = rcvr->klass()->prototype_header(); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) + (*BiasedLocking::revoked_lock_entry_count_addr())++; + } + } else if ((anticipated_bias_locking_value & epoch_mask_in_place) != 0) { + // Try to rebias. + markOop new_header = (markOop) ( (intptr_t) rcvr->klass()->prototype_header() | thread_ident); + if (hash != markOopDesc::no_hash) { + new_header = new_header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::rebiased_lock_entry_count_addr())++; } } else { - cas_label: - success = false; + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); } - } - if (!success) { - markOop displaced = rcvr->mark()->set_unlocked(); - mon->lock()->set_displaced_header(displaced); - if (Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - mon->lock()->set_displaced_header(NULL); - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + success = true; + } else { + // Try to bias towards thread in case object is anonymously biased. + markOop header = (markOop) ((uintptr_t) mark & + ((uintptr_t)markOopDesc::biased_lock_mask_in_place | + (uintptr_t)markOopDesc::age_mask_in_place | epoch_mask_in_place)); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + markOop new_header = (markOop) ((uintptr_t) header | thread_ident); + // Debugging hint. + DEBUG_ONLY(mon->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) + if (Atomic::cmpxchg_ptr((void*)new_header, rcvr->mark_addr(), header) == header) { + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; } + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); + } + success = true; + } + } + + // Traditional lightweight locking. + if (!success) { + markOop displaced = rcvr->mark()->set_unlocked(); + mon->lock()->set_displaced_header(displaced); + bool call_vm = UseHeavyMonitors; + if (call_vm || Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + mon->lock()->set_displaced_header(NULL); + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); } } + } } THREAD->clr_do_not_unlock(); @@ -881,15 +865,84 @@ BytecodeInterpreter::run(interpreterState istate) { BasicObjectLock* entry = (BasicObjectLock*) istate->stack_base(); assert(entry->obj() == NULL, "Frame manager didn't allocate the monitor"); entry->set_obj(lockee); + bool success = false; + uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; - markOop displaced = lockee->mark()->set_unlocked(); - entry->lock()->set_displaced_header(displaced); - if (Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - entry->lock()->set_displaced_header(NULL); + markOop mark = lockee->mark(); + intptr_t hash = (intptr_t) markOopDesc::no_hash; + // implies UseBiasedLocking + if (mark->has_bias_pattern()) { + uintptr_t thread_ident; + uintptr_t anticipated_bias_locking_value; + thread_ident = (uintptr_t)istate->thread(); + anticipated_bias_locking_value = + (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & + ~((uintptr_t) markOopDesc::age_mask_in_place); + + if (anticipated_bias_locking_value == 0) { + // already biased towards this thread, nothing to do + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::biased_lock_entry_count_addr())++; + } + success = true; + } else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { + // try revoke bias + markOop header = lockee->klass()->prototype_header(); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) { + (*BiasedLocking::revoked_lock_entry_count_addr())++; + } + } + } else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) { + // try rebias + markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident); + if (hash != markOopDesc::no_hash) { + new_header = new_header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::rebiased_lock_entry_count_addr())++; + } + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } + success = true; } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + // try to bias towards thread in case object is anonymously biased + markOop header = (markOop) ((uintptr_t) mark & ((uintptr_t)markOopDesc::biased_lock_mask_in_place | + (uintptr_t)markOopDesc::age_mask_in_place | epoch_mask_in_place)); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + markOop new_header = (markOop) ((uintptr_t) header | thread_ident); + // debugging hint + DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) + if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) { + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; + } + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } + success = true; + } + } + + // traditional lightweight locking + if (!success) { + markOop displaced = lockee->mark()->set_unlocked(); + entry->lock()->set_displaced_header(displaced); + bool call_vm = UseHeavyMonitors; + if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + entry->lock()->set_displaced_header(NULL); + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } } } UPDATE_PC_AND_TOS(1, -1); @@ -1700,14 +1753,87 @@ run: } if (entry != NULL) { entry->set_obj(lockee); - markOop displaced = lockee->mark()->set_unlocked(); - entry->lock()->set_displaced_header(displaced); - if (Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { - entry->lock()->set_displaced_header(NULL); - } else { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + int success = false; + uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place; + + markOop mark = lockee->mark(); + intptr_t hash = (intptr_t) markOopDesc::no_hash; + // implies UseBiasedLocking + if (mark->has_bias_pattern()) { + uintptr_t thread_ident; + uintptr_t anticipated_bias_locking_value; + thread_ident = (uintptr_t)istate->thread(); + anticipated_bias_locking_value = + (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & + ~((uintptr_t) markOopDesc::age_mask_in_place); + + if (anticipated_bias_locking_value == 0) { + // already biased towards this thread, nothing to do + if (PrintBiasedLockingStatistics) { + (* BiasedLocking::biased_lock_entry_count_addr())++; + } + success = true; + } + else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { + // try revoke bias + markOop header = lockee->klass()->prototype_header(); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) + (*BiasedLocking::revoked_lock_entry_count_addr())++; + } + } + else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) { + // try rebias + markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident); + if (hash != markOopDesc::no_hash) { + new_header = new_header->copy_set_hash(hash); + } + if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) { + if (PrintBiasedLockingStatistics) + (* BiasedLocking::rebiased_lock_entry_count_addr())++; + } + else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } + success = true; + } + else { + // try to bias towards thread in case object is anonymously biased + markOop header = (markOop) ((uintptr_t) mark & ((uintptr_t)markOopDesc::biased_lock_mask_in_place | + (uintptr_t)markOopDesc::age_mask_in_place | + epoch_mask_in_place)); + if (hash != markOopDesc::no_hash) { + header = header->copy_set_hash(hash); + } + markOop new_header = (markOop) ((uintptr_t) header | thread_ident); + // debugging hint + DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) + if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) { + if (PrintBiasedLockingStatistics) + (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; + } + else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } + success = true; + } + } + + // traditional lightweight locking + if (!success) { + markOop displaced = lockee->mark()->set_unlocked(); + entry->lock()->set_displaced_header(displaced); + bool call_vm = UseHeavyMonitors; + if (call_vm || Atomic::cmpxchg_ptr(entry, lockee->mark_addr(), displaced) != displaced) { + // Is it simple recursive case? + if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) { + entry->lock()->set_displaced_header(NULL); + } else { + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); + } } } UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); @@ -1729,12 +1855,15 @@ run: BasicLock* lock = most_recent->lock(); markOop header = lock->displaced_header(); most_recent->set_obj(NULL); - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL) { - if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { - // restore object for the slow case - most_recent->set_obj(lockee); - CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception); + if (!lockee->mark()->has_bias_pattern()) { + bool call_vm = UseHeavyMonitors; + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL || call_vm) { + if (call_vm || Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { + // restore object for the slow case + most_recent->set_obj(lockee); + CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception); + } } } UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); @@ -2678,15 +2807,18 @@ handle_return: BasicLock* lock = end->lock(); markOop header = lock->displaced_header(); end->set_obj(NULL); - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL) { - if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { - // restore object for the slow case - end->set_obj(lockee); - { - // Prevent any HandleMarkCleaner from freeing our live handles - HandleMark __hm(THREAD); - CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, end)); + + if (!lockee->mark()->has_bias_pattern()) { + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL) { + if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) { + // restore object for the slow case + end->set_obj(lockee); + { + // Prevent any HandleMarkCleaner from freeing our live handles + HandleMark __hm(THREAD); + CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, end)); + } } } } @@ -2735,23 +2867,37 @@ handle_return: illegal_state_oop = THREAD->pending_exception(); THREAD->clear_pending_exception(); } + } else if (UseHeavyMonitors) { + { + // Prevent any HandleMarkCleaner from freeing our live handles. + HandleMark __hm(THREAD); + CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); + } + if (THREAD->has_pending_exception()) { + if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); + THREAD->clear_pending_exception(); + } } else { BasicLock* lock = base->lock(); markOop header = lock->displaced_header(); base->set_obj(NULL); - // If it isn't recursive we either must swap old header or call the runtime - if (header != NULL) { - if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) { - // restore object for the slow case - base->set_obj(rcvr); - { - // Prevent any HandleMarkCleaner from freeing our live handles - HandleMark __hm(THREAD); - CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); - } - if (THREAD->has_pending_exception()) { - if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); - THREAD->clear_pending_exception(); + + if (!rcvr->mark()->has_bias_pattern()) { + base->set_obj(NULL); + // If it isn't recursive we either must swap old header or call the runtime + if (header != NULL) { + if (Atomic::cmpxchg_ptr(header, rcvr->mark_addr(), lock) != lock) { + // restore object for the slow case + base->set_obj(rcvr); + { + // Prevent any HandleMarkCleaner from freeing our live handles + HandleMark __hm(THREAD); + CALL_VM_NOCHECK(InterpreterRuntime::monitorexit(THREAD, base)); + } + if (THREAD->has_pending_exception()) { + if (!suppress_error) illegal_state_oop = THREAD->pending_exception(); + THREAD->clear_pending_exception(); + } } } } @@ -2759,6 +2905,8 @@ handle_return: } } } + // Clear the do_not_unlock flag now. + THREAD->clr_do_not_unlock(); // // Notify jvmti/jvmdi @@ -3130,9 +3278,9 @@ BytecodeInterpreter::print() { } extern "C" { - void PI(uintptr_t arg) { - ((BytecodeInterpreter*)arg)->print(); - } + void PI(uintptr_t arg) { + ((BytecodeInterpreter*)arg)->print(); + } } #endif // PRODUCT From c12f5a0180118f107fa3ccbf6ad0d5f704b7679a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 4 Jul 2013 10:51:31 +0200 Subject: [PATCH 006/265] 8016696: PPC64 (part 4): add relocation for trampoline stubs A trampoline allows to encode a small branch in the code, even if there is the chance that this branch can not reach all possible code locations. If the relocation finds that a branch is too far for the instruction in the code, it can patch it to jump to the trampoline where is sufficient space for a far branch. Needed on PPC. Reviewed-by: kvn, bdelsart, jrose --- hotspot/src/share/vm/code/relocInfo.cpp | 37 ++++++++++++++++++++++ hotspot/src/share/vm/code/relocInfo.hpp | 42 +++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/code/relocInfo.cpp b/hotspot/src/share/vm/code/relocInfo.cpp index 4fe6a2e4949..4b839b845c2 100644 --- a/hotspot/src/share/vm/code/relocInfo.cpp +++ b/hotspot/src/share/vm/code/relocInfo.cpp @@ -582,6 +582,18 @@ void static_stub_Relocation::unpack_data() { _static_call = address_from_scaled_offset(unpack_1_int(), base); } +void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) { + short* p = (short*) dest->locs_end(); + CodeSection* insts = dest->outer()->insts(); + normalize_address(_owner, insts); + p = pack_1_int_to(p, scaled_offset(_owner, insts->start())); + dest->set_locs_end((relocInfo*) p); +} + +void trampoline_stub_Relocation::unpack_data() { + address base = binding()->section_start(CodeBuffer::SECT_INSTS); + _owner = address_from_scaled_offset(unpack_1_int(), base); +} void external_word_Relocation::pack_data_to(CodeSection* dest) { short* p = (short*) dest->locs_end(); @@ -811,6 +823,25 @@ address static_call_Relocation::static_stub() { return NULL; } +// Finds the trampoline address for a call. If no trampoline stub is +// found NULL is returned which can be handled by the caller. +address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* code) { + // There are no relocations available when the code gets relocated + // because of CodeBuffer expansion. + if (code->relocation_size() == 0) + return NULL; + + RelocIterator iter(code, call); + while (iter.next()) { + if (iter.type() == relocInfo::trampoline_stub_type) { + if (iter.trampoline_stub_reloc()->owner() == call) { + return iter.addr(); + } + } + } + + return NULL; +} void static_stub_Relocation::clear_inline_cache() { // Call stub is only used when calling the interpreted code. @@ -975,6 +1006,12 @@ void RelocIterator::print_current() { tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call()); break; } + case relocInfo::trampoline_stub_type: + { + trampoline_stub_Relocation* r = (trampoline_stub_Relocation*) reloc(); + tty->print(" | [trampoline owner=" INTPTR_FORMAT "]", r->owner()); + break; + } } tty->cr(); } diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index 68a7f3a5889..2b8611ca294 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.hpp @@ -260,8 +260,8 @@ class relocInfo VALUE_OBJ_CLASS_SPEC { poll_type = 10, // polling instruction for safepoints poll_return_type = 11, // polling instruction for safepoints at return metadata_type = 12, // metadata that used to be oops - yet_unused_type_1 = 13, // Still unused - yet_unused_type_2 = 14, // Still unused + trampoline_stub_type = 13, // stub-entry for trampoline + yet_unused_type_1 = 14, // Still unused data_prefix_tag = 15, // tag for a prefix (carries data arguments) type_mask = 15 // A mask which selects only the above values }; @@ -301,6 +301,7 @@ class relocInfo VALUE_OBJ_CLASS_SPEC { visitor(poll) \ visitor(poll_return) \ visitor(section_word) \ + visitor(trampoline_stub) \ public: @@ -1150,6 +1151,43 @@ class runtime_call_Relocation : public CallRelocation { public: }; +// Trampoline Relocations. +// A trampoline allows to encode a small branch in the code, even if there +// is the chance that this branch can not reach all possible code locations. +// If the relocation finds that a branch is too far for the instruction +// in the code, it can patch it to jump to the trampoline where is +// sufficient space for a far branch. Needed on PPC. +class trampoline_stub_Relocation : public Relocation { + relocInfo::relocType type() { return relocInfo::trampoline_stub_type; } + + public: + static RelocationHolder spec(address static_call) { + RelocationHolder rh = newHolder(); + return (new (rh) trampoline_stub_Relocation(static_call)); + } + + private: + address _owner; // Address of the NativeCall that owns the trampoline. + + trampoline_stub_Relocation(address owner) { + _owner = owner; + } + + friend class RelocIterator; + trampoline_stub_Relocation() { } + + public: + + // Return the address of the NativeCall that owns the trampoline. + address owner() { return _owner; } + + void pack_data_to(CodeSection * dest); + void unpack_data(); + + // Find the trampoline stub for a call. + static address get_trampoline_for(address call, nmethod* code); +}; + class external_word_Relocation : public DataRelocation { relocInfo::relocType type() { return relocInfo::external_word_type; } From 7c47a187f26e1618be138cb3b59cb20d9b396d95 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 3 Jul 2013 01:29:13 +0200 Subject: [PATCH 007/265] 8019517: PPC64 (part 102): cppInterpreter: implement G1 support Reviewed-by: kvn --- .../vm/interpreter/bytecodeInterpreter.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index af858fa04db..0242ca5a8fe 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -30,7 +30,6 @@ #include "interpreter/bytecodeInterpreter.inline.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" -#include "memory/cardTableModRefBS.hpp" #include "memory/resourceArea.hpp" #include "oops/methodCounters.hpp" #include "oops/objArrayKlass.hpp" @@ -503,8 +502,6 @@ BytecodeInterpreter::run(interpreterState istate) { interpreterState orig = istate; #endif - static volatile jbyte* _byte_map_base; // adjusted card table base for oop store barrier - register intptr_t* topOfStack = (intptr_t *)istate->stack(); /* access with STACK macros */ register address pc = istate->bcp(); register jubyte opcode; @@ -512,12 +509,9 @@ BytecodeInterpreter::run(interpreterState istate) { register ConstantPoolCache* cp = istate->constants(); // method()->constants()->cache() #ifdef LOTS_OF_REGS register JavaThread* THREAD = istate->thread(); - register volatile jbyte* BYTE_MAP_BASE = _byte_map_base; #else #undef THREAD #define THREAD istate->thread() -#undef BYTE_MAP_BASE -#define BYTE_MAP_BASE _byte_map_base #endif #ifdef USELABELS @@ -630,9 +624,6 @@ BytecodeInterpreter::run(interpreterState istate) { #ifdef VM_JVMTI _jvmti_interp_events = JvmtiExport::can_post_interpreter_events(); #endif - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); - _byte_map_base = (volatile jbyte*)(((CardTableModRefBS*)bs)->byte_map_base); return; } break; @@ -1708,11 +1699,7 @@ run: VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), ""); } } - oop* elem_loc = (oop*)(((address) arrObj->base(T_OBJECT)) + index * sizeof(oop)); - // *(oop*)(((address) arrObj->base(T_OBJECT)) + index * sizeof(oop)) = rhsObject; - *elem_loc = rhsObject; - // Mark the card - OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)elem_loc >> CardTableModRefBS::card_shift], 0); + ((objArrayOopDesc *) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } CASE(_bastore): @@ -2052,7 +2039,6 @@ run: } else if (tos_type == atos) { VERIFY_OOP(STACK_OBJECT(-1)); obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); - OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)obj >> CardTableModRefBS::card_shift], 0); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); } else if (tos_type == ltos) { @@ -2073,7 +2059,6 @@ run: } else if (tos_type == atos) { VERIFY_OOP(STACK_OBJECT(-1)); obj->obj_field_put(field_offset, STACK_OBJECT(-1)); - OrderAccess::release_store(&BYTE_MAP_BASE[(uintptr_t)obj >> CardTableModRefBS::card_shift], 0); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); } else if (tos_type == ltos) { From 8cc4fad115932227b61b99b2370b17f9b2f7878c Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 3 Jul 2013 01:41:42 +0200 Subject: [PATCH 008/265] 8019518: PPC64 (part 103): cppInterpreter: implement support for compressed Oops Reviewed-by: kvn, coleenp --- hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 0242ca5a8fe..29b35ba26e7 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1644,8 +1644,11 @@ run: ARRAY_LOADTO32(T_INT, jint, "%d", STACK_INT, 0); CASE(_faload): ARRAY_LOADTO32(T_FLOAT, jfloat, "%f", STACK_FLOAT, 0); - CASE(_aaload): - ARRAY_LOADTO32(T_OBJECT, oop, INTPTR_FORMAT, STACK_OBJECT, 0); + CASE(_aaload): { + ARRAY_INTRO(-2); + SET_STACK_OBJECT(((objArrayOop) arrObj)->obj_at(index), -2); + UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); + } CASE(_baload): ARRAY_LOADTO32(T_BYTE, jbyte, "%d", STACK_INT, 0); CASE(_caload): From 6514fe679471ccc4f6b47dd34b7f98cc34cce232 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 3 Jul 2013 11:25:06 +0200 Subject: [PATCH 009/265] 8019519: PPC64 (part 105): C interpreter: implement support for jvmti early return Reviewed-by: sspitsyn, kvn --- .../vm/interpreter/bytecodeInterpreter.cpp | 130 +++++++++++++----- .../vm/interpreter/bytecodeInterpreter.hpp | 26 ++-- 2 files changed, 106 insertions(+), 50 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 29b35ba26e7..224fa42227e 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -35,6 +35,7 @@ #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" @@ -197,6 +198,10 @@ !THREAD->pop_frame_in_process()) { \ goto handle_Pop_Frame; \ } \ + if (THREAD->jvmti_thread_state() && \ + THREAD->jvmti_thread_state()->is_earlyret_pending()) { \ + goto handle_Early_Return; \ + } \ opcode = *pc; \ } \ } \ @@ -411,21 +416,25 @@ CACHE_LOCALS(); // Call the VM don't check for pending exceptions -#define CALL_VM_NOCHECK(func) \ - DECACHE_STATE(); \ - SET_LAST_JAVA_FRAME(); \ - func; \ - RESET_LAST_JAVA_FRAME(); \ - CACHE_STATE(); \ - if (THREAD->pop_frame_pending() && \ - !THREAD->pop_frame_in_process()) { \ - goto handle_Pop_Frame; \ - } +#define CALL_VM_NOCHECK(func) \ + DECACHE_STATE(); \ + SET_LAST_JAVA_FRAME(); \ + func; \ + RESET_LAST_JAVA_FRAME(); \ + CACHE_STATE(); \ + if (THREAD->pop_frame_pending() && \ + !THREAD->pop_frame_in_process()) { \ + goto handle_Pop_Frame; \ + } \ + if (THREAD->jvmti_thread_state() && \ + THREAD->jvmti_thread_state()->is_earlyret_pending()) { \ + goto handle_Early_Return; \ + } // Call the VM and check for pending exceptions -#define CALL_VM(func, label) { \ - CALL_VM_NOCHECK(func); \ - if (THREAD->has_pending_exception()) goto label; \ +#define CALL_VM(func, label) { \ + CALL_VM_NOCHECK(func); \ + if (THREAD->has_pending_exception()) goto label; \ } /* @@ -783,7 +792,6 @@ BytecodeInterpreter::run(interpreterState istate) { case popping_frame: { // returned from a java call to pop the frame, restart the call // clear the message so we don't confuse ourselves later - ShouldNotReachHere(); // we don't return this. assert(THREAD->pop_frame_in_process(), "wrong frame pop state"); istate->set_msg(no_request); THREAD->clr_pop_frame_in_process(); @@ -811,6 +819,10 @@ BytecodeInterpreter::run(interpreterState istate) { if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) { goto handle_Pop_Frame; } + if (THREAD->jvmti_thread_state() && + THREAD->jvmti_thread_state()->is_earlyret_pending()) { + goto handle_Early_Return; + } if (THREAD->has_pending_exception()) goto handle_exception; // Update the pc by the saved amount of the invoke bytecode size @@ -2708,32 +2720,81 @@ run: // No handler in this activation, unwind and try again THREAD->set_pending_exception(except_oop(), NULL, 0); goto handle_return; - } /* handle_exception: */ - - + } // handle_exception: // Return from an interpreter invocation with the result of the interpretation // on the top of the Java Stack (or a pending exception) -handle_Pop_Frame: + handle_Pop_Frame: { - // We don't really do anything special here except we must be aware - // that we can get here without ever locking the method (if sync). - // Also we skip the notification of the exit. + // We don't really do anything special here except we must be aware + // that we can get here without ever locking the method (if sync). + // Also we skip the notification of the exit. - istate->set_msg(popping_frame); - // Clear pending so while the pop is in process - // we don't start another one if a call_vm is done. - THREAD->clr_pop_frame_pending(); - // Let interpreter (only) see the we're in the process of popping a frame - THREAD->set_pop_frame_in_process(); + istate->set_msg(popping_frame); + // Clear pending so while the pop is in process + // we don't start another one if a call_vm is done. + THREAD->clr_pop_frame_pending(); + // Let interpreter (only) see the we're in the process of popping a frame + THREAD->set_pop_frame_in_process(); -handle_return: - { + goto handle_return; + + } // handle_Pop_Frame + + // ForceEarlyReturn ends a method, and returns to the caller with a return value + // given by the invoker of the early return. + handle_Early_Return: { + + istate->set_msg(early_return); + + // Clear expression stack. + topOfStack = istate->stack_base() - Interpreter::stackElementWords; + + JvmtiThreadState *ts = THREAD->jvmti_thread_state(); + + // Push the value to be returned. + switch (istate->method()->result_type()) { + case T_BOOLEAN: + case T_SHORT: + case T_BYTE: + case T_CHAR: + case T_INT: + SET_STACK_INT(->earlyret_value().i, 0); + MORE_STACK(1); + break; + case T_LONG: + SET_STACK_LONG(ts->earlyret_value().j, 1); + MORE_STACK(2); + break; + case T_FLOAT: + SET_STACK_FLOAT(ts->earlyret_value().f, 0); + MORE_STACK(1); + break; + case T_DOUBLE: + SET_STACK_DOUBLE(ts->earlyret_value().d, 1); + MORE_STACK(2); + break; + case T_ARRAY: + case T_OBJECT: + SET_STACK_OBJECT(ts->earlyret_oop(), 0); + MORE_STACK(1); + break; + } + + ts->clr_earlyret_value(); + ts->set_earlyret_oop(NULL); + ts->clr_earlyret_pending(); + + // Fall through to handle_return. + + } // handle_Early_Return + + handle_return: { DECACHE_STATE(); - bool suppress_error = istate->msg() == popping_frame; - bool suppress_exit_event = THREAD->has_pending_exception() || suppress_error; + bool suppress_error = istate->msg() == popping_frame || istate->msg() == early_return; + bool suppress_exit_event = THREAD->has_pending_exception() || istate->msg() == popping_frame; Handle original_exception(THREAD, THREAD->pending_exception()); Handle illegal_state_oop(THREAD, NULL); @@ -2946,7 +3007,6 @@ handle_return: THREAD->set_pending_exception(illegal_state_oop(), NULL, 0); else THREAD->set_pending_exception(original_exception(), NULL, 0); - istate->set_return_kind((Bytecodes::Code)opcode); UPDATE_PC_AND_RETURN(0); } @@ -2965,13 +3025,12 @@ handle_return: LOCALS_SLOT(METHOD->size_of_parameters() - 1)); THREAD->set_popframe_condition_bit(JavaThread::popframe_force_deopt_reexecution_bit); } - THREAD->clr_pop_frame_in_process(); + } else { + istate->set_msg(return_from_method); } // Normal return // Advance the pc and return to frame manager - istate->set_msg(return_from_method); - istate->set_return_kind((Bytecodes::Code)opcode); UPDATE_PC_AND_RETURN(1); } /* handle_return: */ @@ -3246,7 +3305,6 @@ BytecodeInterpreter::print() { tty->print_cr("result_to_call._bcp_advance: %d ", this->_result._to_call._bcp_advance); tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf); tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry); - tty->print_cr("result_return_kind 0x%x ", (int) this->_result._return_kind); tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link); tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp); tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp index d528034d3f0..b2a1c49683f 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp @@ -66,27 +66,26 @@ union VMJavaVal64 { typedef class BytecodeInterpreter* interpreterState; struct call_message { - class Method* _callee; /* method to call during call_method request */ - address _callee_entry_point; /* address to jump to for call_method request */ - int _bcp_advance; /* size of the invoke bytecode operation */ + class Method* _callee; // method to call during call_method request + address _callee_entry_point; // address to jump to for call_method request + int _bcp_advance; // size of the invoke bytecode operation }; struct osr_message { - address _osr_buf; /* the osr buffer */ - address _osr_entry; /* the entry to the osr method */ + address _osr_buf; // the osr buffer + address _osr_entry; // the entry to the osr method }; struct osr_result { - nmethod* nm; /* osr nmethod */ - address return_addr; /* osr blob return address */ + nmethod* nm; // osr nmethod + address return_addr; // osr blob return address }; // Result returned to frame manager union frame_manager_message { - call_message _to_call; /* describes callee */ - Bytecodes::Code _return_kind; /* i_return, a_return, ... */ - osr_message _osr; /* describes the osr */ - osr_result _osr_result; /* result of OSR request */ + call_message _to_call; // describes callee + osr_message _osr; // describes the osr + osr_result _osr_result; // result of OSR request }; class BytecodeInterpreter : StackObj { @@ -115,7 +114,8 @@ public: more_monitors, // need a new monitor throwing_exception, // unwind stack and rethrow popping_frame, // unwind call and retry call - do_osr // request this invocation be OSR's + do_osr, // request this invocation be OSR's + early_return // early return as commanded by jvmti }; private: @@ -216,8 +216,6 @@ inline void set_osr_entry(address entry) { _result._osr._osr_entry = entry; } inline int bcp_advance() { return _result._to_call._bcp_advance; } inline void set_bcp_advance(int count) { _result._to_call._bcp_advance = count; } -inline void set_return_kind(Bytecodes::Code kind) { _result._return_kind = kind; } - inline interpreterState prev() { return _prev_link; } inline intptr_t* stack() { return _stack; } From 1519be52415ab7ce636e9465bd63061e6d095533 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Tue, 9 Jul 2013 14:28:07 +0200 Subject: [PATCH 010/265] 8020121: PPC64: fix build in cppInterpreter after 8019519 Reviewed-by: kvn --- hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 224fa42227e..4723cf15333 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2760,7 +2760,7 @@ run: case T_BYTE: case T_CHAR: case T_INT: - SET_STACK_INT(->earlyret_value().i, 0); + SET_STACK_INT(ts->earlyret_value().i, 0); MORE_STACK(1); break; case T_LONG: From 49c4939936667fe91a9a0749fdc670ac18a35d3f Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 10 Jul 2013 09:14:25 -0700 Subject: [PATCH 011/265] 8019922: PPC64 (part 8): Implement Linux/PPC64 support in HotSpot makefiles HotSpot make changes to build the HotSpot on Linux/PPC64 Reviewed-by: dholmes, kvn --- hotspot/make/Makefile | 18 +++++----- hotspot/make/defs.make | 11 ++++-- hotspot/make/linux/makefiles/buildtree.make | 1 + hotspot/make/linux/makefiles/defs.make | 11 +++++- hotspot/make/linux/makefiles/gcc.make | 6 +++- hotspot/make/linux/makefiles/ppc64.make | 39 +++++++++++++++++++++ hotspot/make/linux/platform_ppc64 | 17 +++++++++ 7 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 hotspot/make/linux/makefiles/ppc64.make create mode 100644 hotspot/make/linux/platform_ppc64 diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 6d1353c292a..5dcf9a7374c 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -177,7 +177,7 @@ $(C2_VM_TARGETS): $(CORE_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_DIR=$(CORE_DIR) BUILD_FLAVOR=$(@:$core=%) VM_TARGET=$@ generic_buildcore $(ALT_OUT) + $(MAKE) BUILD_DIR=$(CORE_DIR) BUILD_FLAVOR=$(@:%core=%) VM_TARGET=$@ generic_buildcore $(ALT_OUT) $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ @@ -478,22 +478,22 @@ endif # Core ifeq ($(JVM_VARIANT_CORE), true) # Common -$(EXPORT_LIB_DIR)/%.jar: $(CORE_DIR)/../generated/%.jar +$(EXPORT_LIB_DIR)/%.jar: $(CORE_BUILD_DIR)/../generated/%.jar $(install-file) -$(EXPORT_INCLUDE_DIR)/%: $(CORE_DIR)/../generated/jvmtifiles/% +$(EXPORT_INCLUDE_DIR)/%: $(CORE_BUILD_DIR)/../generated/jvmtifiles/% $(install-file) # Unix -$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(CORE_DIR)/%.debuginfo +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(CORE_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(CORE_DIR)/%.diz +$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(CORE_BUILD_DIR)/%.diz $(install-file) -$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_DIR)/%.$(LIBRARY_SUFFIX) +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(CORE_BUILD_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.debuginfo: $(CORE_DIR)/%.debuginfo +$(EXPORT_SERVER_DIR)/%.debuginfo: $(CORE_BUILD_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/%.diz: $(CORE_DIR)/%.diz +$(EXPORT_SERVER_DIR)/%.diz: $(CORE_BUILD_DIR)/%.diz $(install-file) endif diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index 5ebf167e290..07a191e479b 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -259,7 +259,7 @@ ifneq ($(OSNAME),windows) # Use uname output for SRCARCH, but deal with platform differences. If ARCH # is not explicitly listed below, it is treated as x86. - SRCARCH = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc zero,$(ARCH))) + SRCARCH = $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 arm ppc ppc64 zero,$(ARCH))) ARCH/ = x86 ARCH/sparc = sparc ARCH/sparc64= sparc @@ -285,6 +285,11 @@ ifneq ($(OSNAME),windows) BUILDARCH = sparcv9 endif endif + ifeq ($(BUILDARCH), ppc) + ifdef LP64 + BUILDARCH = ppc64 + endif + endif # LIBARCH is 1:1 mapping from BUILDARCH LIBARCH = $(LIBARCH/$(BUILDARCH)) @@ -293,12 +298,12 @@ ifneq ($(OSNAME),windows) LIBARCH/sparc = sparc LIBARCH/sparcv9 = sparcv9 LIBARCH/ia64 = ia64 - LIBARCH/ppc64 = ppc + LIBARCH/ppc64 = ppc64 LIBARCH/ppc = ppc LIBARCH/arm = arm LIBARCH/zero = $(ZERO_LIBARCH) - LP64_ARCH = sparcv9 amd64 ia64 zero + LP64_ARCH = sparcv9 amd64 ia64 ppc64 zero endif # Required make macro settings for all platforms diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index fd6c52513fe..150a126f7f0 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -193,6 +193,7 @@ DATA_MODE/i486 = 32 DATA_MODE/sparc = 32 DATA_MODE/sparcv9 = 64 DATA_MODE/amd64 = 64 +DATA_MODE/ppc64 = 64 DATA_MODE = $(DATA_MODE/$(BUILDARCH)) diff --git a/hotspot/make/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make index 778830814ac..377d4f9c59f 100644 --- a/hotspot/make/linux/makefiles/defs.make +++ b/hotspot/make/linux/makefiles/defs.make @@ -120,6 +120,15 @@ ifeq ($(ARCH), ppc) HS_ARCH = ppc endif +# PPC64 +ifeq ($(ARCH), ppc64) + ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = linux-ppc64 + VM_PLATFORM = linux_ppc64 + HS_ARCH = ppc +endif + # On 32 bit linux we build server and client, on 64 bit just server. ifeq ($(JVM_VARIANTS),) ifeq ($(ARCH_DATA_MODEL), 32) @@ -255,7 +264,7 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal -ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) +ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK) $(JVM_VARIANT_CORE)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index 38cf2c03492..9b161726253 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -181,6 +181,7 @@ ARCHFLAG/zero = $(ZERO_ARCHFLAG) ifndef E500V2 ARCHFLAG/ppc = -mcpu=powerpc endif +ARCHFLAG/ppc64 = -m64 CFLAGS += $(ARCHFLAG) AOUT_FLAGS += $(ARCHFLAG) @@ -346,6 +347,7 @@ else DEBUG_CFLAGS/amd64 = -g DEBUG_CFLAGS/arm = -g DEBUG_CFLAGS/ppc = -g + DEBUG_CFLAGS/ppc64 = -g DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) @@ -361,6 +363,7 @@ else FASTDEBUG_CFLAGS/amd64 = -g FASTDEBUG_CFLAGS/arm = -g FASTDEBUG_CFLAGS/ppc = -g + FASTDEBUG_CFLAGS/ppc64 = -g FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) @@ -375,6 +378,7 @@ else OPT_CFLAGS/amd64 = -g OPT_CFLAGS/arm = -g OPT_CFLAGS/ppc = -g + OPT_CFLAGS/ppc64 = -g OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) diff --git a/hotspot/make/linux/makefiles/ppc64.make b/hotspot/make/linux/makefiles/ppc64.make new file mode 100644 index 00000000000..b3e6f27b65e --- /dev/null +++ b/hotspot/make/linux/makefiles/ppc64.make @@ -0,0 +1,39 @@ +# +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# make c code know it is on a 64 bit platform. +CFLAGS += -D_LP64=1 + +# fixes `relocation truncated to fit' error for gcc 4.1. +CFLAGS += -mminimal-toc + +# finds use ppc64 instructions, but schedule for power5 +CFLAGS += -mcpu=powerpc64 -mtune=power5 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string + +# let linker find external 64 bit libs. +LFLAGS_VM += -L/lib64 + +# specify lib format. +LFLAGS_VM += -Wl,-melf64ppc diff --git a/hotspot/make/linux/platform_ppc64 b/hotspot/make/linux/platform_ppc64 new file mode 100644 index 00000000000..2fd79c4dae9 --- /dev/null +++ b/hotspot/make/linux/platform_ppc64 @@ -0,0 +1,17 @@ +os_family = linux + +arch = ppc + +arch_model = ppc_64 + +os_arch = linux_ppc + +os_arch_model = linux_ppc_64 + +lib_arch = ppc64 + +compiler = gcc + +gnu_dis_arch = ppc64 + +sysdefs = -DLINUX -D_GNU_SOURCE -DPPC64 From b57506ea6c4293e0cace5f4b132652dc63384770 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 5 Jul 2013 22:17:47 +0200 Subject: [PATCH 012/265] 8019973: PPC64 (part 11): Fix IA64 preprocessor conditionals on AIX On AIX 7.1 systemcfg.h defines IA64 unconditionally, so test for !AIX where IA64 is used. Reviewed-by: dholmes, kvn --- hotspot/src/share/vm/opto/generateOptoStub.cpp | 2 +- hotspot/src/share/vm/opto/output.cpp | 2 +- hotspot/src/share/vm/prims/forte.cpp | 8 ++++---- hotspot/src/share/vm/runtime/objectMonitor.cpp | 2 +- hotspot/src/share/vm/runtime/os.cpp | 2 +- hotspot/src/share/vm/runtime/synchronizer.cpp | 2 +- hotspot/src/share/vm/utilities/macros.hpp | 6 +++++- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index c5ebd5ad524..a229faaee1e 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -214,7 +214,7 @@ void GraphKit::gen_stub(address C_function, #if defined(SPARC) store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); #endif /* defined(SPARC) */ -#ifdef IA64 +#if (defined(IA64) && !defined(AIX)) Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias); diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index f04ab721b97..897b4755366 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1065,7 +1065,7 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) { // Compute prolog code size _method_size = 0; _frame_slots = OptoReg::reg2stack(_matcher->_old_SP)+_regalloc->_framesize; -#ifdef IA64 +#if defined(IA64) && !defined(AIX) if (save_argument_registers()) { // 4815101: this is a stub with implicit and unknown precision fp args. // The usual spill mechanism can only generate stfd's in this case, which diff --git a/hotspot/src/share/vm/prims/forte.cpp b/hotspot/src/share/vm/prims/forte.cpp index 43da7494417..e0d3524f31d 100644 --- a/hotspot/src/share/vm/prims/forte.cpp +++ b/hotspot/src/share/vm/prims/forte.cpp @@ -70,7 +70,7 @@ enum { // Native interfaces for use by Forte tools. -#ifndef IA64 +#if !defined(IA64) && !defined(PPC64) class vframeStreamForte : public vframeStreamCommon { public: @@ -624,16 +624,16 @@ void collector_func_load(char* name, #endif // !_WINDOWS } // end extern "C" -#endif // !IA64 +#endif // !IA64 && !PPC64 void Forte::register_stub(const char* name, address start, address end) { -#if !defined(_WINDOWS) && !defined(IA64) +#if !defined(_WINDOWS) && !defined(IA64) && !defined(PPC64) assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX, "Code size exceeds maximum range"); collector_func_load((char*)name, NULL, NULL, start, pointer_delta(end, start, sizeof(jbyte)), 0, NULL); -#endif // !_WINDOWS && !IA64 +#endif // !_WINDOWS && !IA64 && !PPC64 } #else // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 523887502ca..b889107547a 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -54,7 +54,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) +#if defined(__GNUC__) && !defined(IA64) && !defined(PPC64) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 93a60cd06d6..36c90932ac0 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1020,7 +1020,7 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { // if C stack is walkable beyond current frame. The check for fp() is not // necessary on Sparc, but it's harmless. bool os::is_first_C_frame(frame* fr) { -#if defined(IA64) && !defined(_WIN32) +#if (defined(IA64) && !defined(AIX)) && !defined(_WIN32) // On IA64 we have to check if the callers bsp is still valid // (i.e. within the register stack bounds). // Notice: this only works for threads created by the VM and only if diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 015dd757b23..d96a454bb62 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -53,7 +53,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(PPC64) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 6b9ca01f42f..5d56097259b 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -320,7 +320,11 @@ #define NOT_IA32(code) code #endif -#ifdef IA64 +// This is a REALLY BIG HACK, but on AIX unconditionally defines IA64. +// At least on AIX 7.1 this is a real problem because 'systemcfg.h' is indirectly included +// by 'pthread.h' and other common system headers. + +#if defined(IA64) && !defined(AIX) #define IA64_ONLY(code) code #define NOT_IA64(code) #else From d656c7e2b89d2f9d145ffb056844bf63eccebb31 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Fri, 26 Jul 2013 10:12:15 +0200 Subject: [PATCH 013/265] 8019926: PPC64 (part 106): Make hsdis build and work on Linux/PPC64 Make hsdis work on Linux/PPC64 and AIX/PPC64 Reviewed-by: kvn --- hotspot/src/share/tools/hsdis/Makefile | 24 ++++++++++++++++++++---- hotspot/src/share/tools/hsdis/README | 23 ++++++++++++++++++++++- hotspot/src/share/tools/hsdis/hsdis.c | 8 ++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/tools/hsdis/Makefile b/hotspot/src/share/tools/hsdis/Makefile index 2a48f9a81d8..2fb08210ab2 100644 --- a/hotspot/src/share/tools/hsdis/Makefile +++ b/hotspot/src/share/tools/hsdis/Makefile @@ -27,6 +27,7 @@ # Default arch; it is changed below as needed. ARCH = i386 OS = $(shell uname) +AR = ar ## OS = SunOS ## ifeq ($(OS),SunOS) @@ -73,6 +74,7 @@ ARCH=$(ARCH1:i686=i386) ifdef LP64 CFLAGS/sparcv9 += -m64 CFLAGS/amd64 += -m64 +CFLAGS/ppc64 += -m64 else ARCH=$(ARCH1:amd64=i386) CFLAGS/i386 += -m32 @@ -88,8 +90,20 @@ CFLAGS += -O DLDFLAGS += -shared LDFLAGS += -ldl OUTFLAGS += -o $@ -## OS = Windows ## -else # !SunOS, !Linux => Darwin or Windows +else +## OS = AIX ## +ifeq ($(OS),AIX) +OS = aix +ARCH = ppc64 +CC = xlc_r +CFLAGS += -DAIX -g -qpic=large -q64 +CFLAGS/ppc64 += -q64 +AR = ar -X64 +DLDFLAGS += -qmkshrobj -lz +OUTFLAGS += -o $@ +LIB_EXT = .so +else +## OS = Darwin ## ifeq ($(OS),Darwin) CPU = $(shell uname -m) ARCH1=$(CPU:x86_64=amd64) @@ -113,7 +127,8 @@ DLDFLAGS += -shared DLDFLAGS += -lz LDFLAGS += -ldl OUTFLAGS += -o $@ -else #Windows +else +## OS = Windows ## OS = windows CC = gcc CFLAGS += /nologo /MD /W3 /WX /O2 /Fo$(@:.dll=.obj) /Gi- @@ -123,6 +138,7 @@ DLDFLAGS += /dll /subsystem:windows /incremental:no \ OUTFLAGS += /link /out:$@ LIB_EXT = .dll endif # Darwin +endif # AIX endif # Linux endif # SunOS @@ -176,7 +192,7 @@ $(LIBRARIES): $(TARGET_DIR) $(TARGET_DIR)/Makefile if [ ! -f $@ ]; then cd $(TARGET_DIR); make all-opcodes; fi $(TARGET_DIR)/Makefile: - (cd $(TARGET_DIR); CC=$(CC) CFLAGS="$(CFLAGS)" $(BINUTILSDIR)/configure --disable-nls $(CONFIGURE_ARGS)) + (cd $(TARGET_DIR); CC=$(CC) CFLAGS="$(CFLAGS)" AR="$(AR)" $(BINUTILSDIR)/configure --disable-nls $(CONFIGURE_ARGS)) $(TARGET): $(SOURCE) $(LIBS) $(LIBRARIES) $(TARGET_DIR) $(CC) $(OUTFLAGS) $(CPPFLAGS) $(CFLAGS) $(SOURCE) $(DLDFLAGS) $(LIBRARIES) diff --git a/hotspot/src/share/tools/hsdis/README b/hotspot/src/share/tools/hsdis/README index 51caa4051e9..dbebc540b0a 100644 --- a/hotspot/src/share/tools/hsdis/README +++ b/hotspot/src/share/tools/hsdis/README @@ -1,4 +1,4 @@ -Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 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,6 +54,17 @@ explicitly build the 64 bit version. By default this will build the disassembler library only. If you build demo it will build a demo program that attempts to exercise the library. +With recent version of binutils (i.e. binutils-2.23.2) you may get the +following build error: + +WARNING: `makeinfo' is missing on your system. You should only need it if + you modified a `.texi' or `.texinfo' file, or any other file + ... + +This is because of "Bug 15345 - binutils-2.23.2 tarball doesn't build +without makeinfo" [2]. The easiest way to work around this problem is +by doing a "touch $BINUTILS/bfd/doc/bfd.info". + Windows In theory this should be buildable on Windows but getting a working @@ -101,3 +112,13 @@ Now test: If the product mode of the JVM does not accept -XX:+PrintAssembly, you do not have a version new enough to use the hsdis plugin. + +* Wiki + +More information can be found in the OpenJDK HotSpot Wiki [1]. + + +Resources: + +[1] https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly +[2] http://sourceware.org/bugzilla/show_bug.cgi?id=15345 diff --git a/hotspot/src/share/tools/hsdis/hsdis.c b/hotspot/src/share/tools/hsdis/hsdis.c index 162e2aba3e7..268084d1667 100644 --- a/hotspot/src/share/tools/hsdis/hsdis.c +++ b/hotspot/src/share/tools/hsdis/hsdis.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -307,7 +307,8 @@ static void setup_app_data(struct hsdis_app_data* app_data, app_data->printf_stream, app_data->printf_callback, native_bfd, - app_data->insn_options); + /* On PowerPC we get warnings, if we pass empty options */ + (caller_options == NULL) ? NULL : app_data->insn_options); /* Finish linking together the various callback blocks. */ app_data->dinfo.application_data = (void*) app_data; @@ -458,6 +459,9 @@ static const char* native_arch_name() { #endif #ifdef LIBARCH_sparcv9 res = "sparc:v9b"; +#endif +#ifdef LIBARCH_ppc64 + res = "powerpc:common64"; #endif if (res == NULL) res = "architecture not set in Makefile!"; From cf98cb05ca094da1c33e9a53ac33f84feb654053 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 2 Aug 2013 16:46:45 +0200 Subject: [PATCH 014/265] 8019972: PPC64 (part 9): platform files for interpreter only VM With this change the HotSpot core build works on Linux/PPC64. The VM succesfully executes simple test programs. Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/assembler_ppc.cpp | 699 ++++ hotspot/src/cpu/ppc/vm/assembler_ppc.hpp | 1963 ++++++++++ .../src/cpu/ppc/vm/assembler_ppc.inline.hpp | 792 ++++ .../cpu/ppc/vm/bytecodeInterpreter_ppc.hpp | 105 + .../ppc/vm/bytecodeInterpreter_ppc.inline.hpp | 290 ++ hotspot/src/cpu/ppc/vm/bytecodes_ppc.cpp | 31 + hotspot/src/cpu/ppc/vm/bytecodes_ppc.hpp | 31 + hotspot/src/cpu/ppc/vm/bytes_ppc.hpp | 156 + hotspot/src/cpu/ppc/vm/codeBuffer_ppc.hpp | 35 + hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp | 261 ++ hotspot/src/cpu/ppc/vm/copy_ppc.hpp | 167 + .../ppc/vm/cppInterpreterGenerator_ppc.hpp | 43 + hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp | 3044 ++++++++++++++++ hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.hpp | 39 + hotspot/src/cpu/ppc/vm/debug_ppc.cpp | 35 + hotspot/src/cpu/ppc/vm/depChecker_ppc.hpp | 31 + hotspot/src/cpu/ppc/vm/disassembler_ppc.hpp | 37 + hotspot/src/cpu/ppc/vm/frame_ppc.cpp | 306 ++ hotspot/src/cpu/ppc/vm/frame_ppc.hpp | 449 +++ hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp | 239 ++ .../src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 34 + hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 116 + hotspot/src/cpu/ppc/vm/icBuffer_ppc.cpp | 71 + hotspot/src/cpu/ppc/vm/icache_ppc.cpp | 77 + hotspot/src/cpu/ppc/vm/icache_ppc.hpp | 44 + hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp | 504 +++ hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp | 89 + .../cpu/ppc/vm/interpreterGenerator_ppc.hpp | 37 + hotspot/src/cpu/ppc/vm/interpreterRT_ppc.cpp | 150 + hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp | 62 + hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp | 736 ++++ hotspot/src/cpu/ppc/vm/interpreter_ppc.hpp | 42 + .../src/cpu/ppc/vm/javaFrameAnchor_ppc.hpp | 82 + .../src/cpu/ppc/vm/jniFastGetField_ppc.cpp | 75 + hotspot/src/cpu/ppc/vm/jniTypes_ppc.hpp | 110 + hotspot/src/cpu/ppc/vm/jni_ppc.h | 53 + hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 3017 ++++++++++++++++ hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp | 658 ++++ .../cpu/ppc/vm/macroAssembler_ppc.inline.hpp | 382 ++ .../src/cpu/ppc/vm/metaspaceShared_ppc.cpp | 61 + hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp | 540 +++ hotspot/src/cpu/ppc/vm/methodHandles_ppc.hpp | 62 + hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp | 382 ++ hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 397 ++ hotspot/src/cpu/ppc/vm/registerMap_ppc.hpp | 45 + .../cpu/ppc/vm/register_definitions_ppc.cpp | 42 + hotspot/src/cpu/ppc/vm/register_ppc.cpp | 77 + hotspot/src/cpu/ppc/vm/register_ppc.hpp | 635 ++++ hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp | 133 + hotspot/src/cpu/ppc/vm/relocInfo_ppc.hpp | 46 + hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 3209 +++++++++++++++++ hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 2057 +++++++++++ .../src/cpu/ppc/vm/stubRoutines_ppc_64.cpp | 40 + .../src/cpu/ppc/vm/stubRoutines_ppc_64.hpp | 40 + hotspot/src/cpu/ppc/vm/vmStructs_ppc.hpp | 41 + hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 472 +++ hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp | 93 + hotspot/src/cpu/ppc/vm/vmreg_ppc.cpp | 51 + hotspot/src/cpu/ppc/vm/vmreg_ppc.hpp | 35 + hotspot/src/cpu/ppc/vm/vmreg_ppc.inline.hpp | 71 + hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 269 ++ .../linux_ppc/vm/atomic_linux_ppc.inline.hpp | 401 ++ .../os_cpu/linux_ppc/vm/globals_linux_ppc.hpp | 54 + .../vm/orderAccess_linux_ppc.inline.hpp | 149 + .../src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp | 607 ++++ .../src/os_cpu/linux_ppc/vm/os_linux_ppc.hpp | 35 + .../vm/prefetch_linux_ppc.inline.hpp | 50 + .../linux_ppc/vm/threadLS_linux_ppc.cpp | 39 + .../linux_ppc/vm/threadLS_linux_ppc.hpp | 36 + .../os_cpu/linux_ppc/vm/thread_linux_ppc.cpp | 36 + .../os_cpu/linux_ppc/vm/thread_linux_ppc.hpp | 83 + .../linux_ppc/vm/vmStructs_linux_ppc.hpp | 55 + hotspot/src/share/vm/runtime/globals.hpp | 2 +- 73 files changed, 25436 insertions(+), 1 deletion(-) create mode 100644 hotspot/src/cpu/ppc/vm/assembler_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/assembler_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp create mode 100644 hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.inline.hpp create mode 100644 hotspot/src/cpu/ppc/vm/bytecodes_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/bytecodes_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/bytes_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/codeBuffer_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/copy_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/debug_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/depChecker_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/disassembler_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/frame_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/frame_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp create mode 100644 hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/globals_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/icBuffer_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/icache_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/icache_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp create mode 100644 hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp create mode 100644 hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/interpreterRT_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/interpreter_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/javaFrameAnchor_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/jniFastGetField_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/jniTypes_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/jni_ppc.h create mode 100644 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp create mode 100644 hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/methodHandles_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/registerMap_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/register_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/register_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/relocInfo_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp create mode 100644 hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp create mode 100644 hotspot/src/cpu/ppc/vm/vmStructs_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/vmreg_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/vmreg_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/vmreg_ppc.inline.hpp create mode 100644 hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.cpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.hpp create mode 100644 hotspot/src/os_cpu/linux_ppc/vm/vmStructs_linux_ppc.hpp diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp new file mode 100644 index 00000000000..76a1cac53f3 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp @@ -0,0 +1,699 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "gc_interface/collectedHeap.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/cardTableModRefBS.hpp" +#include "memory/resourceArea.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#if INCLUDE_ALL_GCS +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" +#include "gc_implementation/g1/heapRegion.hpp" +#endif // INCLUDE_ALL_GCS + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) block_comment(str) +#endif + +int AbstractAssembler::code_fill_byte() { + return 0x00; // illegal instruction 0x00000000 +} + +void Assembler::print_instruction(int inst) { + Unimplemented(); +} + +// Patch instruction `inst' at offset `inst_pos' to refer to +// `dest_pos' and return the resulting instruction. We should have +// pcs, not offsets, but since all is relative, it will work out fine. +int Assembler::patched_branch(int dest_pos, int inst, int inst_pos) { + int m = 0; // mask for displacement field + int v = 0; // new value for displacement field + + switch (inv_op_ppc(inst)) { + case b_op: m = li(-1); v = li(disp(dest_pos, inst_pos)); break; + case bc_op: m = bd(-1); v = bd(disp(dest_pos, inst_pos)); break; + default: ShouldNotReachHere(); + } + return inst & ~m | v; +} + +// Return the offset, relative to _code_begin, of the destination of +// the branch inst at offset pos. +int Assembler::branch_destination(int inst, int pos) { + int r = 0; + switch (inv_op_ppc(inst)) { + case b_op: r = bxx_destination_offset(inst, pos); break; + case bc_op: r = inv_bd_field(inst, pos); break; + default: ShouldNotReachHere(); + } + return r; +} + +// Low-level andi-one-instruction-macro. +void Assembler::andi(Register a, Register s, const int ui16) { + assert(is_uimm(ui16, 16), "must be 16-bit unsigned immediate"); + if (is_power_of_2_long(((jlong) ui16)+1)) { + // pow2minus1 + clrldi(a, s, 64-log2_long((((jlong) ui16)+1))); + } else if (is_power_of_2_long((jlong) ui16)) { + // pow2 + rlwinm(a, s, 0, 31-log2_long((jlong) ui16), 31-log2_long((jlong) ui16)); + } else if (is_power_of_2_long((jlong)-ui16)) { + // negpow2 + clrrdi(a, s, log2_long((jlong)-ui16)); + } else { + andi_(a, s, ui16); + } +} + +// RegisterOrConstant version. +void Assembler::ld(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::ld(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::ld(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::ldx(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::ld(d, 0, roc.as_register()); + else + Assembler::ldx(d, roc.as_register(), s1); + } +} + +void Assembler::lwa(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::lwa(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::lwa(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::lwax(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::lwa(d, 0, roc.as_register()); + else + Assembler::lwax(d, roc.as_register(), s1); + } +} + +void Assembler::lwz(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::lwz(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::lwz(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::lwzx(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::lwz(d, 0, roc.as_register()); + else + Assembler::lwzx(d, roc.as_register(), s1); + } +} + +void Assembler::lha(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::lha(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::lha(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::lhax(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::lha(d, 0, roc.as_register()); + else + Assembler::lhax(d, roc.as_register(), s1); + } +} + +void Assembler::lhz(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::lhz(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::lhz(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::lhzx(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::lhz(d, 0, roc.as_register()); + else + Assembler::lhzx(d, roc.as_register(), s1); + } +} + +void Assembler::lbz(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + if (s1 == noreg) { + int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); + Assembler::lbz(d, simm16_rest, d); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::lbz(d, roc.as_constant(), s1); + } else { + load_const_optimized(d, roc.as_constant()); + Assembler::lbzx(d, d, s1); + } + } else { + if (s1 == noreg) + Assembler::lbz(d, 0, roc.as_register()); + else + Assembler::lbzx(d, roc.as_register(), s1); + } +} + +void Assembler::std(Register d, RegisterOrConstant roc, Register s1, Register tmp) { + if (roc.is_constant()) { + if (s1 == noreg) { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); + Assembler::std(d, simm16_rest, tmp); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::std(d, roc.as_constant(), s1); + } else { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + load_const_optimized(tmp, roc.as_constant()); + Assembler::stdx(d, tmp, s1); + } + } else { + if (s1 == noreg) + Assembler::std(d, 0, roc.as_register()); + else + Assembler::stdx(d, roc.as_register(), s1); + } +} + +void Assembler::stw(Register d, RegisterOrConstant roc, Register s1, Register tmp) { + if (roc.is_constant()) { + if (s1 == noreg) { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); + Assembler::stw(d, simm16_rest, tmp); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::stw(d, roc.as_constant(), s1); + } else { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + load_const_optimized(tmp, roc.as_constant()); + Assembler::stwx(d, tmp, s1); + } + } else { + if (s1 == noreg) + Assembler::stw(d, 0, roc.as_register()); + else + Assembler::stwx(d, roc.as_register(), s1); + } +} + +void Assembler::sth(Register d, RegisterOrConstant roc, Register s1, Register tmp) { + if (roc.is_constant()) { + if (s1 == noreg) { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); + Assembler::sth(d, simm16_rest, tmp); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::sth(d, roc.as_constant(), s1); + } else { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + load_const_optimized(tmp, roc.as_constant()); + Assembler::sthx(d, tmp, s1); + } + } else { + if (s1 == noreg) + Assembler::sth(d, 0, roc.as_register()); + else + Assembler::sthx(d, roc.as_register(), s1); + } +} + +void Assembler::stb(Register d, RegisterOrConstant roc, Register s1, Register tmp) { + if (roc.is_constant()) { + if (s1 == noreg) { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); + Assembler::stb(d, simm16_rest, tmp); + } else if (is_simm(roc.as_constant(), 16)) { + Assembler::stb(d, roc.as_constant(), s1); + } else { + guarantee(tmp != noreg, "Need tmp reg to encode large constants"); + load_const_optimized(tmp, roc.as_constant()); + Assembler::stbx(d, tmp, s1); + } + } else { + if (s1 == noreg) + Assembler::stb(d, 0, roc.as_register()); + else + Assembler::stbx(d, roc.as_register(), s1); + } +} + +void Assembler::add(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + intptr_t c = roc.as_constant(); + assert(is_simm(c, 16), "too big"); + addi(d, s1, (int)c); + } + else add(d, roc.as_register(), s1); +} + +void Assembler::subf(Register d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + intptr_t c = roc.as_constant(); + assert(is_simm(-c, 16), "too big"); + addi(d, s1, (int)-c); + } + else subf(d, roc.as_register(), s1); +} + +void Assembler::cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1) { + if (roc.is_constant()) { + intptr_t c = roc.as_constant(); + assert(is_simm(c, 16), "too big"); + cmpdi(d, s1, (int)c); + } + else cmpd(d, roc.as_register(), s1); +} + +// Load a 64 bit constant. Patchable. +void Assembler::load_const(Register d, long x, Register tmp) { + // 64-bit value: x = xa xb xc xd + int xa = (x >> 48) & 0xffff; + int xb = (x >> 32) & 0xffff; + int xc = (x >> 16) & 0xffff; + int xd = (x >> 0) & 0xffff; + if (tmp == noreg) { + Assembler::lis( d, (int)(short)xa); + Assembler::ori( d, d, (unsigned int)xb); + Assembler::sldi(d, d, 32); + Assembler::oris(d, d, (unsigned int)xc); + Assembler::ori( d, d, (unsigned int)xd); + } else { + // exploit instruction level parallelism if we have a tmp register + assert_different_registers(d, tmp); + Assembler::lis(tmp, (int)(short)xa); + Assembler::lis(d, (int)(short)xc); + Assembler::ori(tmp, tmp, (unsigned int)xb); + Assembler::ori(d, d, (unsigned int)xd); + Assembler::insrdi(d, tmp, 32, 0); + } +} + +// Load a 64 bit constant, optimized, not identifyable. +// Tmp can be used to increase ILP. Set return_simm16_rest=true to get a +// 16 bit immediate offset. +int Assembler::load_const_optimized(Register d, long x, Register tmp, bool return_simm16_rest) { + // Avoid accidentally trying to use R0 for indexed addressing. + assert(d != R0, "R0 not allowed"); + assert_different_registers(d, tmp); + + short xa, xb, xc, xd; // Four 16-bit chunks of const. + long rem = x; // Remaining part of const. + + xd = rem & 0xFFFF; // Lowest 16-bit chunk. + rem = (rem >> 16) + ((unsigned short)xd >> 15); // Compensation for sign extend. + + if (rem == 0) { // opt 1: simm16 + li(d, xd); + return 0; + } + + xc = rem & 0xFFFF; // Next 16-bit chunk. + rem = (rem >> 16) + ((unsigned short)xc >> 15); // Compensation for sign extend. + + if (rem == 0) { // opt 2: simm32 + lis(d, xc); + } else { // High 32 bits needed. + + if (tmp != noreg) { // opt 3: We have a temp reg. + // No carry propagation between xc and higher chunks here (use logical instructions). + xa = (x >> 48) & 0xffff; + xb = (x >> 32) & 0xffff; // No sign compensation, we use lis+ori or li to allow usage of R0. + bool load_xa = (xa != 0) || (xb < 0); + bool return_xd = false; + + if (load_xa) lis(tmp, xa); + if (xc) lis(d, xc); + if (load_xa) { + if (xb) ori(tmp, tmp, xb); // No addi, we support tmp == R0. + } else { + li(tmp, xb); // non-negative + } + if (xc) { + if (return_simm16_rest && xd >= 0) { return_xd = true; } // >= 0 to avoid carry propagation after insrdi/rldimi. + else if (xd) { addi(d, d, xd); } + } else { + li(d, xd); + } + insrdi(d, tmp, 32, 0); + return return_xd ? xd : 0; // non-negative + } + + xb = rem & 0xFFFF; // Next 16-bit chunk. + rem = (rem >> 16) + ((unsigned short)xb >> 15); // Compensation for sign extend. + + xa = rem & 0xFFFF; // Highest 16-bit chunk. + + // opt 4: avoid adding 0 + if (xa) { // Highest 16-bit needed? + lis(d, xa); + if (xb) addi(d, d, xb); + } else { + li(d, xb); + } + sldi(d, d, 32); + if (xc) addis(d, d, xc); + } + + // opt 5: Return offset to be inserted into following instruction. + if (return_simm16_rest) return xd; + + if (xd) addi(d, d, xd); + return 0; +} + +#ifndef PRODUCT +// Test of ppc assembler. +void Assembler::test_asm() { + // PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions + addi( R0, R1, 10); + addis( R5, R2, 11); + addic_( R3, R31, 42); + subfic( R21, R12, 2112); + add( R3, R2, R1); + add_( R11, R22, R30); + subf( R7, R6, R5); + subf_( R8, R9, R4); + addc( R11, R12, R13); + addc_( R14, R14, R14); + subfc( R15, R16, R17); + subfc_( R18, R20, R19); + adde( R20, R22, R24); + adde_( R29, R27, R26); + subfe( R28, R1, R0); + subfe_( R21, R11, R29); + neg( R21, R22); + neg_( R13, R23); + mulli( R0, R11, -31); + mulld( R1, R18, R21); + mulld_( R2, R17, R22); + mullw( R3, R16, R23); + mullw_( R4, R15, R24); + divd( R5, R14, R25); + divd_( R6, R13, R26); + divw( R7, R12, R27); + divw_( R8, R11, R28); + + li( R3, -4711); + + // PPC 1, section 3.3.9, Fixed-Point Compare Instructions + cmpi( CCR7, 0, R27, 4711); + cmp( CCR0, 1, R14, R11); + cmpli( CCR5, 1, R17, 45); + cmpl( CCR3, 0, R9, R10); + + cmpwi( CCR7, R27, 4711); + cmpw( CCR0, R14, R11); + cmplwi( CCR5, R17, 45); + cmplw( CCR3, R9, R10); + + cmpdi( CCR7, R27, 4711); + cmpd( CCR0, R14, R11); + cmpldi( CCR5, R17, 45); + cmpld( CCR3, R9, R10); + + // PPC 1, section 3.3.11, Fixed-Point Logical Instructions + andi_( R4, R5, 0xff); + andis_( R12, R13, 0x7b51); + ori( R1, R4, 13); + oris( R3, R5, 177); + xori( R7, R6, 51); + xoris( R29, R0, 1); + andr( R17, R21, R16); + and_( R3, R5, R15); + orr( R2, R1, R9); + or_( R17, R15, R11); + xorr( R19, R18, R10); + xor_( R31, R21, R11); + nand( R5, R7, R3); + nand_( R3, R1, R0); + nor( R2, R3, R5); + nor_( R3, R6, R8); + andc( R25, R12, R11); + andc_( R24, R22, R21); + orc( R20, R10, R12); + orc_( R22, R2, R13); + + nop(); + + // PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions + sld( R5, R6, R8); + sld_( R3, R5, R9); + slw( R2, R1, R10); + slw_( R6, R26, R16); + srd( R16, R24, R8); + srd_( R21, R14, R7); + srw( R22, R25, R29); + srw_( R5, R18, R17); + srad( R7, R11, R0); + srad_( R9, R13, R1); + sraw( R7, R15, R2); + sraw_( R4, R17, R3); + sldi( R3, R18, 63); + sldi_( R2, R20, 30); + slwi( R1, R21, 30); + slwi_( R7, R23, 8); + srdi( R0, R19, 2); + srdi_( R12, R24, 5); + srwi( R13, R27, 6); + srwi_( R14, R29, 7); + sradi( R15, R30, 9); + sradi_( R16, R31, 19); + srawi( R17, R31, 15); + srawi_( R18, R31, 12); + + clrrdi( R3, R30, 5); + clrldi( R9, R10, 11); + + rldicr( R19, R20, 13, 15); + rldicr_(R20, R20, 16, 14); + rldicl( R21, R21, 30, 33); + rldicl_(R22, R1, 20, 25); + rlwinm( R23, R2, 25, 10, 11); + rlwinm_(R24, R3, 12, 13, 14); + + // PPC 1, section 3.3.2 Fixed-Point Load Instructions + lwzx( R3, R5, R7); + lwz( R11, 0, R1); + lwzu( R31, -4, R11); + + lwax( R3, R5, R7); + lwa( R31, -4, R11); + lhzx( R3, R5, R7); + lhz( R31, -4, R11); + lhzu( R31, -4, R11); + + + lhax( R3, R5, R7); + lha( R31, -4, R11); + lhau( R11, 0, R1); + + lbzx( R3, R5, R7); + lbz( R31, -4, R11); + lbzu( R11, 0, R1); + + ld( R31, -4, R11); + ldx( R3, R5, R7); + ldu( R31, -4, R11); + + // PPC 1, section 3.3.3 Fixed-Point Store Instructions + stwx( R3, R5, R7); + stw( R31, -4, R11); + stwu( R11, 0, R1); + + sthx( R3, R5, R7 ); + sth( R31, -4, R11); + sthu( R31, -4, R11); + + stbx( R3, R5, R7); + stb( R31, -4, R11); + stbu( R31, -4, R11); + + std( R31, -4, R11); + stdx( R3, R5, R7); + stdu( R31, -4, R11); + + // PPC 1, section 3.3.13 Move To/From System Register Instructions + mtlr( R3); + mflr( R3); + mtctr( R3); + mfctr( R3); + mtcrf( 0xff, R15); + mtcr( R15); + mtcrf( 0x03, R15); + mtcr( R15); + mfcr( R15); + + // PPC 1, section 2.4.1 Branch Instructions + Label lbl1, lbl2, lbl3; + bind(lbl1); + + b(pc()); + b(pc() - 8); + b(lbl1); + b(lbl2); + b(lbl3); + + bl(pc() - 8); + bl(lbl1); + bl(lbl2); + + bcl(4, 10, pc() - 8); + bcl(4, 10, lbl1); + bcl(4, 10, lbl2); + + bclr( 4, 6, 0); + bclrl(4, 6, 0); + + bind(lbl2); + + bcctr( 4, 6, 0); + bcctrl(4, 6, 0); + + blt(CCR0, lbl2); + bgt(CCR1, lbl2); + beq(CCR2, lbl2); + bso(CCR3, lbl2); + bge(CCR4, lbl2); + ble(CCR5, lbl2); + bne(CCR6, lbl2); + bns(CCR7, lbl2); + + bltl(CCR0, lbl2); + bgtl(CCR1, lbl2); + beql(CCR2, lbl2); + bsol(CCR3, lbl2); + bgel(CCR4, lbl2); + blel(CCR5, lbl2); + bnel(CCR6, lbl2); + bnsl(CCR7, lbl2); + blr(); + + sync(); + icbi( R1, R2); + dcbst(R2, R3); + + // FLOATING POINT instructions ppc. + // PPC 1, section 4.6.2 Floating-Point Load Instructions + lfs( F1, -11, R3); + lfsu(F2, 123, R4); + lfsx(F3, R5, R6); + lfd( F4, 456, R7); + lfdu(F5, 789, R8); + lfdx(F6, R10, R11); + + // PPC 1, section 4.6.3 Floating-Point Store Instructions + stfs( F7, 876, R12); + stfsu( F8, 543, R13); + stfsx( F9, R14, R15); + stfd( F10, 210, R16); + stfdu( F11, 111, R17); + stfdx( F12, R18, R19); + + // PPC 1, section 4.6.4 Floating-Point Move Instructions + fmr( F13, F14); + fmr_( F14, F15); + fneg( F16, F17); + fneg_( F18, F19); + fabs( F20, F21); + fabs_( F22, F23); + fnabs( F24, F25); + fnabs_(F26, F27); + + // PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic + // Instructions + fadd( F28, F29, F30); + fadd_( F31, F0, F1); + fadds( F2, F3, F4); + fadds_(F5, F6, F7); + fsub( F8, F9, F10); + fsub_( F11, F12, F13); + fsubs( F14, F15, F16); + fsubs_(F17, F18, F19); + fmul( F20, F21, F22); + fmul_( F23, F24, F25); + fmuls( F26, F27, F28); + fmuls_(F29, F30, F31); + fdiv( F0, F1, F2); + fdiv_( F3, F4, F5); + fdivs( F6, F7, F8); + fdivs_(F9, F10, F11); + + // PPC 1, section 4.6.6 Floating-Point Rounding and Conversion + // Instructions + frsp( F12, F13); + fctid( F14, F15); + fctidz(F16, F17); + fctiw( F18, F19); + fctiwz(F20, F21); + fcfid( F22, F23); + + // PPC 1, section 4.6.7 Floating-Point Compare Instructions + fcmpu( CCR7, F24, F25); + + tty->print_cr("\ntest_asm disassembly (0x%lx 0x%lx):", code()->insts_begin(), code()->insts_end()); + code()->decode(); +} +#endif // !PRODUCT diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp new file mode 100644 index 00000000000..896ea3c1954 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -0,0 +1,1963 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_ASSEMBLER_PPC_HPP +#define CPU_PPC_VM_ASSEMBLER_PPC_HPP + +#include "asm/register.hpp" + +// Address is an abstraction used to represent a memory location +// as used in assembler instructions. +// PPC instructions grok either baseReg + indexReg or baseReg + disp. +// So far we do not use this as simplification by this class is low +// on PPC with its simple addressing mode. Use RegisterOrConstant to +// represent an offset. +class Address VALUE_OBJ_CLASS_SPEC { +}; + +class AddressLiteral VALUE_OBJ_CLASS_SPEC { + private: + address _address; + RelocationHolder _rspec; + + RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) { + switch (rtype) { + case relocInfo::external_word_type: + return external_word_Relocation::spec(addr); + case relocInfo::internal_word_type: + return internal_word_Relocation::spec(addr); + case relocInfo::opt_virtual_call_type: + return opt_virtual_call_Relocation::spec(); + case relocInfo::static_call_type: + return static_call_Relocation::spec(); + case relocInfo::runtime_call_type: + return runtime_call_Relocation::spec(); + case relocInfo::none: + return RelocationHolder(); + default: + ShouldNotReachHere(); + return RelocationHolder(); + } + } + + protected: + // creation + AddressLiteral() : _address(NULL), _rspec(NULL) {} + + public: + AddressLiteral(address addr, RelocationHolder const& rspec) + : _address(addr), + _rspec(rspec) {} + + AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(oop* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + intptr_t value() const { return (intptr_t) _address; } + + const RelocationHolder& rspec() const { return _rspec; } +}; + +// Argument is an abstraction used to represent an outgoing +// actual argument or an incoming formal parameter, whether +// it resides in memory or in a register, in a manner consistent +// with the PPC Application Binary Interface, or ABI. This is +// often referred to as the native or C calling convention. + +class Argument VALUE_OBJ_CLASS_SPEC { + private: + int _number; // The number of the argument. + public: + enum { + // Only 8 registers may contain integer parameters. + n_register_parameters = 8, + // Can have up to 8 floating registers. + n_float_register_parameters = 8 + }; + // creation + Argument(int number) : _number(number) {} + + int number() const { return _number; } + + // Locating register-based arguments: + bool is_register() const { return _number < n_register_parameters; } + + Register as_register() const { + assert(is_register(), "must be a register argument"); + return as_Register(number() + R3_ARG1->encoding()); + } +}; + +// A ppc64 function descriptor. +struct FunctionDescriptor VALUE_OBJ_CLASS_SPEC { + private: + address _entry; + address _toc; + address _env; + + public: + inline address entry() const { return _entry; } + inline address toc() const { return _toc; } + inline address env() const { return _env; } + + inline void set_entry(address entry) { _entry = entry; } + inline void set_toc( address toc) { _toc = toc; } + inline void set_env( address env) { _env = env; } + + inline static ByteSize entry_offset() { return byte_offset_of(FunctionDescriptor, _entry); } + inline static ByteSize toc_offset() { return byte_offset_of(FunctionDescriptor, _toc); } + inline static ByteSize env_offset() { return byte_offset_of(FunctionDescriptor, _env); } + + // Friend functions can be called without loading toc and env. + enum { + friend_toc = 0xcafe, + friend_env = 0xc0de + }; + + inline bool is_friend_function() const { + return (toc() == (address) friend_toc) && (env() == (address) friend_env); + } + + // Constructor for stack-allocated instances. + FunctionDescriptor() { + _entry = (address) 0xbad; + _toc = (address) 0xbad; + _env = (address) 0xbad; + } +}; + +class Assembler : public AbstractAssembler { + protected: + // Displacement routines + static void print_instruction(int inst); + static int patched_branch(int dest_pos, int inst, int inst_pos); + static int branch_destination(int inst, int pos); + + friend class AbstractAssembler; + + // Code patchers need various routines like inv_wdisp() + friend class NativeInstruction; + friend class NativeGeneralJump; + friend class Relocation; + + public: + + enum shifts { + XO_21_29_SHIFT = 2, + XO_21_30_SHIFT = 1, + XO_27_29_SHIFT = 2, + XO_30_31_SHIFT = 0, + SPR_5_9_SHIFT = 11u, // SPR_5_9 field in bits 11 -- 15 + SPR_0_4_SHIFT = 16u, // SPR_0_4 field in bits 16 -- 20 + RS_SHIFT = 21u, // RS field in bits 21 -- 25 + OPCODE_SHIFT = 26u, // opcode in bits 26 -- 31 + }; + + enum opcdxos_masks { + XL_FORM_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), + ADDI_OPCODE_MASK = (63u << OPCODE_SHIFT), + ADDIS_OPCODE_MASK = (63u << OPCODE_SHIFT), + BXX_OPCODE_MASK = (63u << OPCODE_SHIFT), + BCXX_OPCODE_MASK = (63u << OPCODE_SHIFT), + // trap instructions + TDI_OPCODE_MASK = (63u << OPCODE_SHIFT), + TWI_OPCODE_MASK = (63u << OPCODE_SHIFT), + TD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), + TW_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), + LD_OPCODE_MASK = (63u << OPCODE_SHIFT) | (3u << XO_30_31_SHIFT), // DS-FORM + STD_OPCODE_MASK = LD_OPCODE_MASK, + STDU_OPCODE_MASK = STD_OPCODE_MASK, + STDX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), + STDUX_OPCODE_MASK = STDX_OPCODE_MASK, + STW_OPCODE_MASK = (63u << OPCODE_SHIFT), + STWU_OPCODE_MASK = STW_OPCODE_MASK, + STWX_OPCODE_MASK = (63u << OPCODE_SHIFT) | (1023u << 1), + STWUX_OPCODE_MASK = STWX_OPCODE_MASK, + MTCTR_OPCODE_MASK = ~(31u << RS_SHIFT), + ORI_OPCODE_MASK = (63u << OPCODE_SHIFT), + ORIS_OPCODE_MASK = (63u << OPCODE_SHIFT), + RLDICR_OPCODE_MASK = (63u << OPCODE_SHIFT) | (7u << XO_27_29_SHIFT) + }; + + enum opcdxos { + ADD_OPCODE = (31u << OPCODE_SHIFT | 266u << 1), + ADDC_OPCODE = (31u << OPCODE_SHIFT | 10u << 1), + ADDI_OPCODE = (14u << OPCODE_SHIFT), + ADDIS_OPCODE = (15u << OPCODE_SHIFT), + ADDIC__OPCODE = (13u << OPCODE_SHIFT), + ADDE_OPCODE = (31u << OPCODE_SHIFT | 138u << 1), + SUBF_OPCODE = (31u << OPCODE_SHIFT | 40u << 1), + SUBFC_OPCODE = (31u << OPCODE_SHIFT | 8u << 1), + SUBFE_OPCODE = (31u << OPCODE_SHIFT | 136u << 1), + SUBFIC_OPCODE = (8u << OPCODE_SHIFT), + SUBFZE_OPCODE = (31u << OPCODE_SHIFT | 200u << 1), + DIVW_OPCODE = (31u << OPCODE_SHIFT | 491u << 1), + MULLW_OPCODE = (31u << OPCODE_SHIFT | 235u << 1), + MULHW_OPCODE = (31u << OPCODE_SHIFT | 75u << 1), + MULHWU_OPCODE = (31u << OPCODE_SHIFT | 11u << 1), + MULLI_OPCODE = (7u << OPCODE_SHIFT), + AND_OPCODE = (31u << OPCODE_SHIFT | 28u << 1), + ANDI_OPCODE = (28u << OPCODE_SHIFT), + ANDIS_OPCODE = (29u << OPCODE_SHIFT), + ANDC_OPCODE = (31u << OPCODE_SHIFT | 60u << 1), + ORC_OPCODE = (31u << OPCODE_SHIFT | 412u << 1), + OR_OPCODE = (31u << OPCODE_SHIFT | 444u << 1), + ORI_OPCODE = (24u << OPCODE_SHIFT), + ORIS_OPCODE = (25u << OPCODE_SHIFT), + XOR_OPCODE = (31u << OPCODE_SHIFT | 316u << 1), + XORI_OPCODE = (26u << OPCODE_SHIFT), + XORIS_OPCODE = (27u << OPCODE_SHIFT), + + NEG_OPCODE = (31u << OPCODE_SHIFT | 104u << 1), + + RLWINM_OPCODE = (21u << OPCODE_SHIFT), + CLRRWI_OPCODE = RLWINM_OPCODE, + CLRLWI_OPCODE = RLWINM_OPCODE, + + RLWIMI_OPCODE = (20u << OPCODE_SHIFT), + + SLW_OPCODE = (31u << OPCODE_SHIFT | 24u << 1), + SLWI_OPCODE = RLWINM_OPCODE, + SRW_OPCODE = (31u << OPCODE_SHIFT | 536u << 1), + SRWI_OPCODE = RLWINM_OPCODE, + SRAW_OPCODE = (31u << OPCODE_SHIFT | 792u << 1), + SRAWI_OPCODE = (31u << OPCODE_SHIFT | 824u << 1), + + CMP_OPCODE = (31u << OPCODE_SHIFT | 0u << 1), + CMPI_OPCODE = (11u << OPCODE_SHIFT), + CMPL_OPCODE = (31u << OPCODE_SHIFT | 32u << 1), + CMPLI_OPCODE = (10u << OPCODE_SHIFT), + + ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), + + MTLR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1 | 8 << SPR_0_4_SHIFT), + MFLR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1 | 8 << SPR_0_4_SHIFT), + + MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), + MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), + MCRF_OPCODE = (19u << OPCODE_SHIFT | 0u << 1), + + // condition register logic instructions + CRAND_OPCODE = (19u << OPCODE_SHIFT | 257u << 1), + CRNAND_OPCODE = (19u << OPCODE_SHIFT | 225u << 1), + CROR_OPCODE = (19u << OPCODE_SHIFT | 449u << 1), + CRXOR_OPCODE = (19u << OPCODE_SHIFT | 193u << 1), + CRNOR_OPCODE = (19u << OPCODE_SHIFT | 33u << 1), + CREQV_OPCODE = (19u << OPCODE_SHIFT | 289u << 1), + CRANDC_OPCODE = (19u << OPCODE_SHIFT | 129u << 1), + CRORC_OPCODE = (19u << OPCODE_SHIFT | 417u << 1), + + BCLR_OPCODE = (19u << OPCODE_SHIFT | 16u << 1), + BXX_OPCODE = (18u << OPCODE_SHIFT), + BCXX_OPCODE = (16u << OPCODE_SHIFT), + + // CTR-related opcodes + BCCTR_OPCODE = (19u << OPCODE_SHIFT | 528u << 1), + MTCTR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1 | 9 << SPR_0_4_SHIFT), + MFCTR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1 | 9 << SPR_0_4_SHIFT), + + + LWZ_OPCODE = (32u << OPCODE_SHIFT), + LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), + LWZU_OPCODE = (33u << OPCODE_SHIFT), + + LHA_OPCODE = (42u << OPCODE_SHIFT), + LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1), + LHAU_OPCODE = (43u << OPCODE_SHIFT), + + LHZ_OPCODE = (40u << OPCODE_SHIFT), + LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1), + LHZU_OPCODE = (41u << OPCODE_SHIFT), + + LBZ_OPCODE = (34u << OPCODE_SHIFT), + LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1), + LBZU_OPCODE = (35u << OPCODE_SHIFT), + + STW_OPCODE = (36u << OPCODE_SHIFT), + STWX_OPCODE = (31u << OPCODE_SHIFT | 151u << 1), + STWU_OPCODE = (37u << OPCODE_SHIFT), + STWUX_OPCODE = (31u << OPCODE_SHIFT | 183u << 1), + + STH_OPCODE = (44u << OPCODE_SHIFT), + STHX_OPCODE = (31u << OPCODE_SHIFT | 407u << 1), + STHU_OPCODE = (45u << OPCODE_SHIFT), + + STB_OPCODE = (38u << OPCODE_SHIFT), + STBX_OPCODE = (31u << OPCODE_SHIFT | 215u << 1), + STBU_OPCODE = (39u << OPCODE_SHIFT), + + EXTSB_OPCODE = (31u << OPCODE_SHIFT | 954u << 1), + EXTSH_OPCODE = (31u << OPCODE_SHIFT | 922u << 1), + EXTSW_OPCODE = (31u << OPCODE_SHIFT | 986u << 1), // X-FORM + + // 32 bit opcode encodings + + LWA_OPCODE = (58u << OPCODE_SHIFT | 2u << XO_30_31_SHIFT), // DS-FORM + LWAX_OPCODE = (31u << OPCODE_SHIFT | 341u << XO_21_30_SHIFT), // X-FORM + + CNTLZW_OPCODE = (31u << OPCODE_SHIFT | 26u << XO_21_30_SHIFT), // X-FORM + + // 64 bit opcode encodings + + LD_OPCODE = (58u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM + LDU_OPCODE = (58u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM + LDX_OPCODE = (31u << OPCODE_SHIFT | 21u << XO_21_30_SHIFT), // X-FORM + + STD_OPCODE = (62u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM + STDU_OPCODE = (62u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM + STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM + STDX_OPCODE = (31u << OPCODE_SHIFT | 149u << XO_21_30_SHIFT), // X-FORM + + RLDICR_OPCODE = (30u << OPCODE_SHIFT | 1u << XO_27_29_SHIFT), // MD-FORM + RLDICL_OPCODE = (30u << OPCODE_SHIFT | 0u << XO_27_29_SHIFT), // MD-FORM + RLDIC_OPCODE = (30u << OPCODE_SHIFT | 2u << XO_27_29_SHIFT), // MD-FORM + RLDIMI_OPCODE = (30u << OPCODE_SHIFT | 3u << XO_27_29_SHIFT), // MD-FORM + + SRADI_OPCODE = (31u << OPCODE_SHIFT | 413u << XO_21_29_SHIFT), // XS-FORM + + SLD_OPCODE = (31u << OPCODE_SHIFT | 27u << 1), // X-FORM + SRD_OPCODE = (31u << OPCODE_SHIFT | 539u << 1), // X-FORM + SRAD_OPCODE = (31u << OPCODE_SHIFT | 794u << 1), // X-FORM + + MULLD_OPCODE = (31u << OPCODE_SHIFT | 233u << 1), // XO-FORM + MULHD_OPCODE = (31u << OPCODE_SHIFT | 73u << 1), // XO-FORM + MULHDU_OPCODE = (31u << OPCODE_SHIFT | 9u << 1), // XO-FORM + DIVD_OPCODE = (31u << OPCODE_SHIFT | 489u << 1), // XO-FORM + + CNTLZD_OPCODE = (31u << OPCODE_SHIFT | 58u << XO_21_30_SHIFT), // X-FORM + NAND_OPCODE = (31u << OPCODE_SHIFT | 476u << XO_21_30_SHIFT), // X-FORM + NOR_OPCODE = (31u << OPCODE_SHIFT | 124u << XO_21_30_SHIFT), // X-FORM + + + // opcodes only used for floating arithmetic + FADD_OPCODE = (63u << OPCODE_SHIFT | 21u << 1), + FADDS_OPCODE = (59u << OPCODE_SHIFT | 21u << 1), + FCMPU_OPCODE = (63u << OPCODE_SHIFT | 00u << 1), + FDIV_OPCODE = (63u << OPCODE_SHIFT | 18u << 1), + FDIVS_OPCODE = (59u << OPCODE_SHIFT | 18u << 1), + FMR_OPCODE = (63u << OPCODE_SHIFT | 72u << 1), + // These are special Power6 opcodes, reused for "lfdepx" and "stfdepx" + // on Power7. Do not use. + // MFFGPR_OPCODE = (31u << OPCODE_SHIFT | 607u << 1), + // MFTGPR_OPCODE = (31u << OPCODE_SHIFT | 735u << 1), + CMPB_OPCODE = (31u << OPCODE_SHIFT | 508 << 1), + POPCNTB_OPCODE = (31u << OPCODE_SHIFT | 122 << 1), + POPCNTW_OPCODE = (31u << OPCODE_SHIFT | 378 << 1), + POPCNTD_OPCODE = (31u << OPCODE_SHIFT | 506 << 1), + FABS_OPCODE = (63u << OPCODE_SHIFT | 264u << 1), + FNABS_OPCODE = (63u << OPCODE_SHIFT | 136u << 1), + FMUL_OPCODE = (63u << OPCODE_SHIFT | 25u << 1), + FMULS_OPCODE = (59u << OPCODE_SHIFT | 25u << 1), + FNEG_OPCODE = (63u << OPCODE_SHIFT | 40u << 1), + FSUB_OPCODE = (63u << OPCODE_SHIFT | 20u << 1), + FSUBS_OPCODE = (59u << OPCODE_SHIFT | 20u << 1), + + // PPC64-internal FPU conversion opcodes + FCFID_OPCODE = (63u << OPCODE_SHIFT | 846u << 1), + FCFIDS_OPCODE = (59u << OPCODE_SHIFT | 846u << 1), + FCTID_OPCODE = (63u << OPCODE_SHIFT | 814u << 1), + FCTIDZ_OPCODE = (63u << OPCODE_SHIFT | 815u << 1), + FCTIW_OPCODE = (63u << OPCODE_SHIFT | 14u << 1), + FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1), + FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1), + + // WARNING: using fmadd results in a non-compliant vm. Some floating + // point tck tests will fail. + FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1), + DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1), + FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1), + DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1), + FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1), + DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1), + FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1), + DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1), + + LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1), + LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1), + LFDX_OPCODE = (31u << OPCODE_SHIFT | 599u << 1), + LFS_OPCODE = (48u << OPCODE_SHIFT | 00u << 1), + LFSU_OPCODE = (49u << OPCODE_SHIFT | 00u << 1), + LFSX_OPCODE = (31u << OPCODE_SHIFT | 535u << 1), + + STFD_OPCODE = (54u << OPCODE_SHIFT | 00u << 1), + STFDU_OPCODE = (55u << OPCODE_SHIFT | 00u << 1), + STFDX_OPCODE = (31u << OPCODE_SHIFT | 727u << 1), + STFS_OPCODE = (52u << OPCODE_SHIFT | 00u << 1), + STFSU_OPCODE = (53u << OPCODE_SHIFT | 00u << 1), + STFSX_OPCODE = (31u << OPCODE_SHIFT | 663u << 1), + + FSQRT_OPCODE = (63u << OPCODE_SHIFT | 22u << 1), // A-FORM + FSQRTS_OPCODE = (59u << OPCODE_SHIFT | 22u << 1), // A-FORM + + // Vector instruction support for >= Power6 + // Vector Storage Access + LVEBX_OPCODE = (31u << OPCODE_SHIFT | 7u << 1), + LVEHX_OPCODE = (31u << OPCODE_SHIFT | 39u << 1), + LVEWX_OPCODE = (31u << OPCODE_SHIFT | 71u << 1), + LVX_OPCODE = (31u << OPCODE_SHIFT | 103u << 1), + LVXL_OPCODE = (31u << OPCODE_SHIFT | 359u << 1), + STVEBX_OPCODE = (31u << OPCODE_SHIFT | 135u << 1), + STVEHX_OPCODE = (31u << OPCODE_SHIFT | 167u << 1), + STVEWX_OPCODE = (31u << OPCODE_SHIFT | 199u << 1), + STVX_OPCODE = (31u << OPCODE_SHIFT | 231u << 1), + STVXL_OPCODE = (31u << OPCODE_SHIFT | 487u << 1), + LVSL_OPCODE = (31u << OPCODE_SHIFT | 6u << 1), + LVSR_OPCODE = (31u << OPCODE_SHIFT | 38u << 1), + + // Vector Permute and Formatting + VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ), + VPKSHSS_OPCODE = (4u << OPCODE_SHIFT | 398u ), + VPKSWSS_OPCODE = (4u << OPCODE_SHIFT | 462u ), + VPKSHUS_OPCODE = (4u << OPCODE_SHIFT | 270u ), + VPKSWUS_OPCODE = (4u << OPCODE_SHIFT | 334u ), + VPKUHUM_OPCODE = (4u << OPCODE_SHIFT | 14u ), + VPKUWUM_OPCODE = (4u << OPCODE_SHIFT | 78u ), + VPKUHUS_OPCODE = (4u << OPCODE_SHIFT | 142u ), + VPKUWUS_OPCODE = (4u << OPCODE_SHIFT | 206u ), + VUPKHPX_OPCODE = (4u << OPCODE_SHIFT | 846u ), + VUPKHSB_OPCODE = (4u << OPCODE_SHIFT | 526u ), + VUPKHSH_OPCODE = (4u << OPCODE_SHIFT | 590u ), + VUPKLPX_OPCODE = (4u << OPCODE_SHIFT | 974u ), + VUPKLSB_OPCODE = (4u << OPCODE_SHIFT | 654u ), + VUPKLSH_OPCODE = (4u << OPCODE_SHIFT | 718u ), + + VMRGHB_OPCODE = (4u << OPCODE_SHIFT | 12u ), + VMRGHW_OPCODE = (4u << OPCODE_SHIFT | 140u ), + VMRGHH_OPCODE = (4u << OPCODE_SHIFT | 76u ), + VMRGLB_OPCODE = (4u << OPCODE_SHIFT | 268u ), + VMRGLW_OPCODE = (4u << OPCODE_SHIFT | 396u ), + VMRGLH_OPCODE = (4u << OPCODE_SHIFT | 332u ), + + VSPLT_OPCODE = (4u << OPCODE_SHIFT | 524u ), + VSPLTH_OPCODE = (4u << OPCODE_SHIFT | 588u ), + VSPLTW_OPCODE = (4u << OPCODE_SHIFT | 652u ), + VSPLTISB_OPCODE= (4u << OPCODE_SHIFT | 780u ), + VSPLTISH_OPCODE= (4u << OPCODE_SHIFT | 844u ), + VSPLTISW_OPCODE= (4u << OPCODE_SHIFT | 908u ), + + VPERM_OPCODE = (4u << OPCODE_SHIFT | 43u ), + VSEL_OPCODE = (4u << OPCODE_SHIFT | 42u ), + + VSL_OPCODE = (4u << OPCODE_SHIFT | 452u ), + VSLDOI_OPCODE = (4u << OPCODE_SHIFT | 44u ), + VSLO_OPCODE = (4u << OPCODE_SHIFT | 1036u ), + VSR_OPCODE = (4u << OPCODE_SHIFT | 708u ), + VSRO_OPCODE = (4u << OPCODE_SHIFT | 1100u ), + + // Vector Integer + VADDCUW_OPCODE = (4u << OPCODE_SHIFT | 384u ), + VADDSHS_OPCODE = (4u << OPCODE_SHIFT | 832u ), + VADDSBS_OPCODE = (4u << OPCODE_SHIFT | 768u ), + VADDSWS_OPCODE = (4u << OPCODE_SHIFT | 896u ), + VADDUBM_OPCODE = (4u << OPCODE_SHIFT | 0u ), + VADDUWM_OPCODE = (4u << OPCODE_SHIFT | 128u ), + VADDUHM_OPCODE = (4u << OPCODE_SHIFT | 64u ), + VADDUBS_OPCODE = (4u << OPCODE_SHIFT | 512u ), + VADDUWS_OPCODE = (4u << OPCODE_SHIFT | 640u ), + VADDUHS_OPCODE = (4u << OPCODE_SHIFT | 576u ), + VSUBCUW_OPCODE = (4u << OPCODE_SHIFT | 1408u ), + VSUBSHS_OPCODE = (4u << OPCODE_SHIFT | 1856u ), + VSUBSBS_OPCODE = (4u << OPCODE_SHIFT | 1792u ), + VSUBSWS_OPCODE = (4u << OPCODE_SHIFT | 1920u ), + VSUBUBM_OPCODE = (4u << OPCODE_SHIFT | 1024u ), + VSUBUWM_OPCODE = (4u << OPCODE_SHIFT | 1152u ), + VSUBUHM_OPCODE = (4u << OPCODE_SHIFT | 1088u ), + VSUBUBS_OPCODE = (4u << OPCODE_SHIFT | 1536u ), + VSUBUWS_OPCODE = (4u << OPCODE_SHIFT | 1664u ), + VSUBUHS_OPCODE = (4u << OPCODE_SHIFT | 1600u ), + + VMULESB_OPCODE = (4u << OPCODE_SHIFT | 776u ), + VMULEUB_OPCODE = (4u << OPCODE_SHIFT | 520u ), + VMULESH_OPCODE = (4u << OPCODE_SHIFT | 840u ), + VMULEUH_OPCODE = (4u << OPCODE_SHIFT | 584u ), + VMULOSB_OPCODE = (4u << OPCODE_SHIFT | 264u ), + VMULOUB_OPCODE = (4u << OPCODE_SHIFT | 8u ), + VMULOSH_OPCODE = (4u << OPCODE_SHIFT | 328u ), + VMULOUH_OPCODE = (4u << OPCODE_SHIFT | 72u ), + VMHADDSHS_OPCODE=(4u << OPCODE_SHIFT | 32u ), + VMHRADDSHS_OPCODE=(4u << OPCODE_SHIFT | 33u ), + VMLADDUHM_OPCODE=(4u << OPCODE_SHIFT | 34u ), + VMSUBUHM_OPCODE= (4u << OPCODE_SHIFT | 36u ), + VMSUMMBM_OPCODE= (4u << OPCODE_SHIFT | 37u ), + VMSUMSHM_OPCODE= (4u << OPCODE_SHIFT | 40u ), + VMSUMSHS_OPCODE= (4u << OPCODE_SHIFT | 41u ), + VMSUMUHM_OPCODE= (4u << OPCODE_SHIFT | 38u ), + VMSUMUHS_OPCODE= (4u << OPCODE_SHIFT | 39u ), + + VSUMSWS_OPCODE = (4u << OPCODE_SHIFT | 1928u ), + VSUM2SWS_OPCODE= (4u << OPCODE_SHIFT | 1672u ), + VSUM4SBS_OPCODE= (4u << OPCODE_SHIFT | 1800u ), + VSUM4UBS_OPCODE= (4u << OPCODE_SHIFT | 1544u ), + VSUM4SHS_OPCODE= (4u << OPCODE_SHIFT | 1608u ), + + VAVGSB_OPCODE = (4u << OPCODE_SHIFT | 1282u ), + VAVGSW_OPCODE = (4u << OPCODE_SHIFT | 1410u ), + VAVGSH_OPCODE = (4u << OPCODE_SHIFT | 1346u ), + VAVGUB_OPCODE = (4u << OPCODE_SHIFT | 1026u ), + VAVGUW_OPCODE = (4u << OPCODE_SHIFT | 1154u ), + VAVGUH_OPCODE = (4u << OPCODE_SHIFT | 1090u ), + + VMAXSB_OPCODE = (4u << OPCODE_SHIFT | 258u ), + VMAXSW_OPCODE = (4u << OPCODE_SHIFT | 386u ), + VMAXSH_OPCODE = (4u << OPCODE_SHIFT | 322u ), + VMAXUB_OPCODE = (4u << OPCODE_SHIFT | 2u ), + VMAXUW_OPCODE = (4u << OPCODE_SHIFT | 130u ), + VMAXUH_OPCODE = (4u << OPCODE_SHIFT | 66u ), + VMINSB_OPCODE = (4u << OPCODE_SHIFT | 770u ), + VMINSW_OPCODE = (4u << OPCODE_SHIFT | 898u ), + VMINSH_OPCODE = (4u << OPCODE_SHIFT | 834u ), + VMINUB_OPCODE = (4u << OPCODE_SHIFT | 514u ), + VMINUW_OPCODE = (4u << OPCODE_SHIFT | 642u ), + VMINUH_OPCODE = (4u << OPCODE_SHIFT | 578u ), + + VCMPEQUB_OPCODE= (4u << OPCODE_SHIFT | 6u ), + VCMPEQUH_OPCODE= (4u << OPCODE_SHIFT | 70u ), + VCMPEQUW_OPCODE= (4u << OPCODE_SHIFT | 134u ), + VCMPGTSH_OPCODE= (4u << OPCODE_SHIFT | 838u ), + VCMPGTSB_OPCODE= (4u << OPCODE_SHIFT | 774u ), + VCMPGTSW_OPCODE= (4u << OPCODE_SHIFT | 902u ), + VCMPGTUB_OPCODE= (4u << OPCODE_SHIFT | 518u ), + VCMPGTUH_OPCODE= (4u << OPCODE_SHIFT | 582u ), + VCMPGTUW_OPCODE= (4u << OPCODE_SHIFT | 646u ), + + VAND_OPCODE = (4u << OPCODE_SHIFT | 1028u ), + VANDC_OPCODE = (4u << OPCODE_SHIFT | 1092u ), + VNOR_OPCODE = (4u << OPCODE_SHIFT | 1284u ), + VOR_OPCODE = (4u << OPCODE_SHIFT | 1156u ), + VXOR_OPCODE = (4u << OPCODE_SHIFT | 1220u ), + VRLB_OPCODE = (4u << OPCODE_SHIFT | 4u ), + VRLW_OPCODE = (4u << OPCODE_SHIFT | 132u ), + VRLH_OPCODE = (4u << OPCODE_SHIFT | 68u ), + VSLB_OPCODE = (4u << OPCODE_SHIFT | 260u ), + VSKW_OPCODE = (4u << OPCODE_SHIFT | 388u ), + VSLH_OPCODE = (4u << OPCODE_SHIFT | 324u ), + VSRB_OPCODE = (4u << OPCODE_SHIFT | 516u ), + VSRW_OPCODE = (4u << OPCODE_SHIFT | 644u ), + VSRH_OPCODE = (4u << OPCODE_SHIFT | 580u ), + VSRAB_OPCODE = (4u << OPCODE_SHIFT | 772u ), + VSRAW_OPCODE = (4u << OPCODE_SHIFT | 900u ), + VSRAH_OPCODE = (4u << OPCODE_SHIFT | 836u ), + + // Vector Floating-Point + // not implemented yet + + // Vector Status and Control + MTVSCR_OPCODE = (4u << OPCODE_SHIFT | 1604u ), + MFVSCR_OPCODE = (4u << OPCODE_SHIFT | 1540u ), + + // Icache and dcache related instructions + DCBA_OPCODE = (31u << OPCODE_SHIFT | 758u << 1), + DCBZ_OPCODE = (31u << OPCODE_SHIFT | 1014u << 1), + DCBST_OPCODE = (31u << OPCODE_SHIFT | 54u << 1), + DCBF_OPCODE = (31u << OPCODE_SHIFT | 86u << 1), + + DCBT_OPCODE = (31u << OPCODE_SHIFT | 278u << 1), + DCBTST_OPCODE = (31u << OPCODE_SHIFT | 246u << 1), + ICBI_OPCODE = (31u << OPCODE_SHIFT | 982u << 1), + + // Instruction synchronization + ISYNC_OPCODE = (19u << OPCODE_SHIFT | 150u << 1), + // Memory barriers + SYNC_OPCODE = (31u << OPCODE_SHIFT | 598u << 1), + EIEIO_OPCODE = (31u << OPCODE_SHIFT | 854u << 1), + + // Trap instructions + TDI_OPCODE = (2u << OPCODE_SHIFT), + TWI_OPCODE = (3u << OPCODE_SHIFT), + TD_OPCODE = (31u << OPCODE_SHIFT | 68u << 1), + TW_OPCODE = (31u << OPCODE_SHIFT | 4u << 1), + + // Atomics. + LWARX_OPCODE = (31u << OPCODE_SHIFT | 20u << 1), + LDARX_OPCODE = (31u << OPCODE_SHIFT | 84u << 1), + STWCX_OPCODE = (31u << OPCODE_SHIFT | 150u << 1), + STDCX_OPCODE = (31u << OPCODE_SHIFT | 214u << 1) + + }; + + // Trap instructions TO bits + enum trap_to_bits { + // single bits + traptoLessThanSigned = 1 << 4, // 0, left end + traptoGreaterThanSigned = 1 << 3, + traptoEqual = 1 << 2, + traptoLessThanUnsigned = 1 << 1, + traptoGreaterThanUnsigned = 1 << 0, // 4, right end + + // compound ones + traptoUnconditional = (traptoLessThanSigned | + traptoGreaterThanSigned | + traptoEqual | + traptoLessThanUnsigned | + traptoGreaterThanUnsigned) + }; + + // Branch hints BH field + enum branch_hint_bh { + // bclr cases: + bhintbhBCLRisReturn = 0, + bhintbhBCLRisNotReturnButSame = 1, + bhintbhBCLRisNotPredictable = 3, + + // bcctr cases: + bhintbhBCCTRisNotReturnButSame = 0, + bhintbhBCCTRisNotPredictable = 3 + }; + + // Branch prediction hints AT field + enum branch_hint_at { + bhintatNoHint = 0, // at=00 + bhintatIsNotTaken = 2, // at=10 + bhintatIsTaken = 3 // at=11 + }; + + // Branch prediction hints + enum branch_hint_concept { + // Use the same encoding as branch_hint_at to simply code. + bhintNoHint = bhintatNoHint, + bhintIsNotTaken = bhintatIsNotTaken, + bhintIsTaken = bhintatIsTaken + }; + + // Used in BO field of branch instruction. + enum branch_condition { + bcondCRbiIs0 = 4, // bo=001at + bcondCRbiIs1 = 12, // bo=011at + bcondAlways = 20 // bo=10100 + }; + + // Branch condition with combined prediction hints. + enum branch_condition_with_hint { + bcondCRbiIs0_bhintNoHint = bcondCRbiIs0 | bhintatNoHint, + bcondCRbiIs0_bhintIsNotTaken = bcondCRbiIs0 | bhintatIsNotTaken, + bcondCRbiIs0_bhintIsTaken = bcondCRbiIs0 | bhintatIsTaken, + bcondCRbiIs1_bhintNoHint = bcondCRbiIs1 | bhintatNoHint, + bcondCRbiIs1_bhintIsNotTaken = bcondCRbiIs1 | bhintatIsNotTaken, + bcondCRbiIs1_bhintIsTaken = bcondCRbiIs1 | bhintatIsTaken, + }; + + // Branch prediction hints. + inline static int add_bhint_to_boint(const int bhint, const int boint) { + switch (boint) { + case bcondCRbiIs0: + case bcondCRbiIs1: + // branch_hint and branch_hint_at have same encodings + assert( (int)bhintNoHint == (int)bhintatNoHint + && (int)bhintIsNotTaken == (int)bhintatIsNotTaken + && (int)bhintIsTaken == (int)bhintatIsTaken, + "wrong encodings"); + assert((bhint & 0x03) == bhint, "wrong encodings"); + return (boint & ~0x03) | bhint; + case bcondAlways: + // no branch_hint + return boint; + default: + ShouldNotReachHere(); + return 0; + } + } + + // Extract bcond from boint. + inline static int inv_boint_bcond(const int boint) { + int r_bcond = boint & ~0x03; + assert(r_bcond == bcondCRbiIs0 || + r_bcond == bcondCRbiIs1 || + r_bcond == bcondAlways, + "bad branch condition"); + return r_bcond; + } + + // Extract bhint from boint. + inline static int inv_boint_bhint(const int boint) { + int r_bhint = boint & 0x03; + assert(r_bhint == bhintatNoHint || + r_bhint == bhintatIsNotTaken || + r_bhint == bhintatIsTaken, + "bad branch hint"); + return r_bhint; + } + + // Calculate opposite of given bcond. + inline static int opposite_bcond(const int bcond) { + switch (bcond) { + case bcondCRbiIs0: + return bcondCRbiIs1; + case bcondCRbiIs1: + return bcondCRbiIs0; + default: + ShouldNotReachHere(); + return 0; + } + } + + // Calculate opposite of given bhint. + inline static int opposite_bhint(const int bhint) { + switch (bhint) { + case bhintatNoHint: + return bhintatNoHint; + case bhintatIsNotTaken: + return bhintatIsTaken; + case bhintatIsTaken: + return bhintatIsNotTaken; + default: + ShouldNotReachHere(); + return 0; + } + } + + // PPC branch instructions + enum ppcops { + b_op = 18, + bc_op = 16, + bcr_op = 19 + }; + + enum Condition { + negative = 0, + less = 0, + positive = 1, + greater = 1, + zero = 2, + equal = 2, + summary_overflow = 3, + }; + + public: + // Helper functions for groups of instructions + + enum Predict { pt = 1, pn = 0 }; // pt = predict taken + + enum Membar_mask_bits { // page 184, v9 + StoreStore = 1 << 3, + LoadStore = 1 << 2, + StoreLoad = 1 << 1, + LoadLoad = 1 << 0, + + Sync = 1 << 6, + MemIssue = 1 << 5, + Lookaside = 1 << 4 + }; + + // instruction must start at passed address + static int instr_len(unsigned char *instr) { return BytesPerInstWord; } + + // instruction must be left-justified in argument + static int instr_len(unsigned long instr) { return BytesPerInstWord; } + + // longest instructions + static int instr_maxlen() { return BytesPerInstWord; } + + // Test if x is within signed immediate range for nbits. + static bool is_simm(int x, unsigned int nbits) { + assert(0 < nbits && nbits < 32, "out of bounds"); + const int min = -( ((int)1) << nbits-1 ); + const int maxplus1 = ( ((int)1) << nbits-1 ); + return min <= x && x < maxplus1; + } + + static bool is_simm(jlong x, unsigned int nbits) { + assert(0 < nbits && nbits < 64, "out of bounds"); + const jlong min = -( ((jlong)1) << nbits-1 ); + const jlong maxplus1 = ( ((jlong)1) << nbits-1 ); + return min <= x && x < maxplus1; + } + + // Test if x is within unsigned immediate range for nbits + static bool is_uimm(int x, unsigned int nbits) { + assert(0 < nbits && nbits < 32, "out of bounds"); + const int maxplus1 = ( ((int)1) << nbits ); + return 0 <= x && x < maxplus1; + } + + static bool is_uimm(jlong x, unsigned int nbits) { + assert(0 < nbits && nbits < 64, "out of bounds"); + const jlong maxplus1 = ( ((jlong)1) << nbits ); + return 0 <= x && x < maxplus1; + } + + protected: + // helpers + + // X is supposed to fit in a field "nbits" wide + // and be sign-extended. Check the range. + static void assert_signed_range(intptr_t x, int nbits) { + assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), + "value out of range"); + } + + static void assert_signed_word_disp_range(intptr_t x, int nbits) { + assert((x & 3) == 0, "not word aligned"); + assert_signed_range(x, nbits + 2); + } + + static void assert_unsigned_const(int x, int nbits) { + assert(juint(x) < juint(1 << nbits), "unsigned constant out of range"); + } + + static int fmask(juint hi_bit, juint lo_bit) { + assert(hi_bit >= lo_bit && hi_bit < 32, "bad bits"); + return (1 << ( hi_bit-lo_bit + 1 )) - 1; + } + + // inverse of u_field + static int inv_u_field(int x, int hi_bit, int lo_bit) { + juint r = juint(x) >> lo_bit; + r &= fmask(hi_bit, lo_bit); + return int(r); + } + + // signed version: extract from field and sign-extend + static int inv_s_field_ppc(int x, int hi_bit, int lo_bit) { + x = x << (31-hi_bit); + x = x >> (31-hi_bit+lo_bit); + return x; + } + + static int u_field(int x, int hi_bit, int lo_bit) { + assert((x & ~fmask(hi_bit, lo_bit)) == 0, "value out of range"); + int r = x << lo_bit; + assert(inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); + return r; + } + + // Same as u_field for signed values + static int s_field(int x, int hi_bit, int lo_bit) { + int nbits = hi_bit - lo_bit + 1; + assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), + "value out of range"); + x &= fmask(hi_bit, lo_bit); + int r = x << lo_bit; + return r; + } + + // inv_op for ppc instructions + static int inv_op_ppc(int x) { return inv_u_field(x, 31, 26); } + + // Determine target address from li, bd field of branch instruction. + static intptr_t inv_li_field(int x) { + intptr_t r = inv_s_field_ppc(x, 25, 2); + r = (r << 2); + return r; + } + static intptr_t inv_bd_field(int x, intptr_t pos) { + intptr_t r = inv_s_field_ppc(x, 15, 2); + r = (r << 2) + pos; + return r; + } + + #define inv_opp_u_field(x, hi_bit, lo_bit) inv_u_field(x, 31-(lo_bit), 31-(hi_bit)) + #define inv_opp_s_field(x, hi_bit, lo_bit) inv_s_field_ppc(x, 31-(lo_bit), 31-(hi_bit)) + // Extract instruction fields from instruction words. + public: + static int inv_ra_field(int x) { return inv_opp_u_field(x, 15, 11); } + static int inv_rb_field(int x) { return inv_opp_u_field(x, 20, 16); } + static int inv_rt_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_rs_field(int x) { return inv_opp_u_field(x, 10, 6); } + // Ds uses opp_s_field(x, 31, 16), but lowest 2 bits must be 0. + // Inv_ds_field uses range (x, 29, 16) but shifts by 2 to ensure that lowest bits are 0. + static int inv_ds_field(int x) { return inv_opp_s_field(x, 29, 16) << 2; } + static int inv_d1_field(int x) { return inv_opp_s_field(x, 31, 16); } + static int inv_si_field(int x) { return inv_opp_s_field(x, 31, 16); } + static int inv_to_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_lk_field(int x) { return inv_opp_u_field(x, 31, 31); } + static int inv_bo_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_bi_field(int x) { return inv_opp_u_field(x, 15, 11); } + + #define opp_u_field(x, hi_bit, lo_bit) u_field(x, 31-(lo_bit), 31-(hi_bit)) + #define opp_s_field(x, hi_bit, lo_bit) s_field(x, 31-(lo_bit), 31-(hi_bit)) + + // instruction fields + static int aa( int x) { return opp_u_field(x, 30, 30); } + static int ba( int x) { return opp_u_field(x, 15, 11); } + static int bb( int x) { return opp_u_field(x, 20, 16); } + static int bc( int x) { return opp_u_field(x, 25, 21); } + static int bd( int x) { return opp_s_field(x, 29, 16); } + static int bf( ConditionRegister cr) { return bf(cr->encoding()); } + static int bf( int x) { return opp_u_field(x, 8, 6); } + static int bfa(ConditionRegister cr) { return bfa(cr->encoding()); } + static int bfa( int x) { return opp_u_field(x, 13, 11); } + static int bh( int x) { return opp_u_field(x, 20, 19); } + static int bi( int x) { return opp_u_field(x, 15, 11); } + static int bi0(ConditionRegister cr, Condition c) { return (cr->encoding() << 2) | c; } + static int bo( int x) { return opp_u_field(x, 10, 6); } + static int bt( int x) { return opp_u_field(x, 10, 6); } + static int d1( int x) { return opp_s_field(x, 31, 16); } + static int ds( int x) { assert((x & 0x3) == 0, "unaligned offset"); return opp_s_field(x, 31, 16); } + static int eh( int x) { return opp_u_field(x, 31, 31); } + static int flm( int x) { return opp_u_field(x, 14, 7); } + static int fra( FloatRegister r) { return fra(r->encoding());} + static int frb( FloatRegister r) { return frb(r->encoding());} + static int frc( FloatRegister r) { return frc(r->encoding());} + static int frs( FloatRegister r) { return frs(r->encoding());} + static int frt( FloatRegister r) { return frt(r->encoding());} + static int fra( int x) { return opp_u_field(x, 15, 11); } + static int frb( int x) { return opp_u_field(x, 20, 16); } + static int frc( int x) { return opp_u_field(x, 25, 21); } + static int frs( int x) { return opp_u_field(x, 10, 6); } + static int frt( int x) { return opp_u_field(x, 10, 6); } + static int fxm( int x) { return opp_u_field(x, 19, 12); } + static int l10( int x) { return opp_u_field(x, 10, 10); } + static int l15( int x) { return opp_u_field(x, 15, 15); } + static int l910( int x) { return opp_u_field(x, 10, 9); } + static int lev( int x) { return opp_u_field(x, 26, 20); } + static int li( int x) { return opp_s_field(x, 29, 6); } + static int lk( int x) { return opp_u_field(x, 31, 31); } + static int mb2125( int x) { return opp_u_field(x, 25, 21); } + static int me2630( int x) { return opp_u_field(x, 30, 26); } + static int mb2126( int x) { return opp_u_field(((x & 0x1f) << 1) | ((x & 0x20) >> 5), 26, 21); } + static int me2126( int x) { return mb2126(x); } + static int nb( int x) { return opp_u_field(x, 20, 16); } + //static int opcd( int x) { return opp_u_field(x, 5, 0); } // is contained in our opcodes + static int oe( int x) { return opp_u_field(x, 21, 21); } + static int ra( Register r) { return ra(r->encoding()); } + static int ra( int x) { return opp_u_field(x, 15, 11); } + static int rb( Register r) { return rb(r->encoding()); } + static int rb( int x) { return opp_u_field(x, 20, 16); } + static int rc( int x) { return opp_u_field(x, 31, 31); } + static int rs( Register r) { return rs(r->encoding()); } + static int rs( int x) { return opp_u_field(x, 10, 6); } + // we don't want to use R0 in memory accesses, because it has value `0' then + static int ra0mem( Register r) { assert(r != R0, "cannot use register R0 in memory access"); return ra(r); } + static int ra0mem( int x) { assert(x != 0, "cannot use register 0 in memory access"); return ra(x); } + + // register r is target + static int rt( Register r) { return rs(r); } + static int rt( int x) { return rs(x); } + static int rta( Register r) { return ra(r); } + static int rta0mem( Register r) { rta(r); return ra0mem(r); } + + static int sh1620( int x) { return opp_u_field(x, 20, 16); } + static int sh30( int x) { return opp_u_field(x, 30, 30); } + static int sh162030( int x) { return sh1620(x & 0x1f) | sh30((x & 0x20) >> 5); } + static int si( int x) { return opp_s_field(x, 31, 16); } + static int spr( int x) { return opp_u_field(x, 20, 11); } + static int sr( int x) { return opp_u_field(x, 15, 12); } + static int tbr( int x) { return opp_u_field(x, 20, 11); } + static int th( int x) { return opp_u_field(x, 10, 7); } + static int thct( int x) { assert((x&8)==0, "must be valid cache specification"); return th(x); } + static int thds( int x) { assert((x&8)==8, "must be valid stream specification"); return th(x); } + static int to( int x) { return opp_u_field(x, 10, 6); } + static int u( int x) { return opp_u_field(x, 19, 16); } + static int ui( int x) { return opp_u_field(x, 31, 16); } + + // support vector instructions for >= Power6 + static int vra( int x) { return opp_u_field(x, 15, 11); } + static int vrb( int x) { return opp_u_field(x, 20, 16); } + static int vrc( int x) { return opp_u_field(x, 25, 21); } + static int vrs( int x) { return opp_u_field(x, 10, 6); } + static int vrt( int x) { return opp_u_field(x, 10, 6); } + + static int vra( VectorRegister r) { return vra(r->encoding());} + static int vrb( VectorRegister r) { return vrb(r->encoding());} + static int vrc( VectorRegister r) { return vrc(r->encoding());} + static int vrs( VectorRegister r) { return vrs(r->encoding());} + static int vrt( VectorRegister r) { return vrt(r->encoding());} + + static int vsplt_uim( int x) { return opp_u_field(x, 15, 12); } // for vsplt* instructions + static int vsplti_sim(int x) { return opp_u_field(x, 15, 11); } // for vsplti* instructions + static int vsldoi_shb(int x) { return opp_u_field(x, 25, 22); } // for vsldoi instruction + static int vcmp_rc( int x) { return opp_u_field(x, 21, 21); } // for vcmp* instructions + + //static int xo1( int x) { return opp_u_field(x, 29, 21); }// is contained in our opcodes + //static int xo2( int x) { return opp_u_field(x, 30, 21); }// is contained in our opcodes + //static int xo3( int x) { return opp_u_field(x, 30, 22); }// is contained in our opcodes + //static int xo4( int x) { return opp_u_field(x, 30, 26); }// is contained in our opcodes + //static int xo5( int x) { return opp_u_field(x, 29, 27); }// is contained in our opcodes + //static int xo6( int x) { return opp_u_field(x, 30, 27); }// is contained in our opcodes + //static int xo7( int x) { return opp_u_field(x, 31, 30); }// is contained in our opcodes + + protected: + // Compute relative address for branch. + static intptr_t disp(intptr_t x, intptr_t off) { + int xx = x - off; + xx = xx >> 2; + return xx; + } + + public: + // signed immediate, in low bits, nbits long + static int simm(int x, int nbits) { + assert_signed_range(x, nbits); + return x & ((1 << nbits) - 1); + } + + // unsigned immediate, in low bits, nbits long + static int uimm(int x, int nbits) { + assert_unsigned_const(x, nbits); + return x & ((1 << nbits) - 1); + } + + static void set_imm(int* instr, short s) { + short* p = ((short *)instr) + 1; + *p = s; + } + + static int get_imm(address a, int instruction_number) { + short imm; + short *p =((short *)a)+2*instruction_number+1; + imm = *p; + return (int)imm; + } + + static inline int hi16_signed( int x) { return (int)(int16_t)(x >> 16); } + static inline int lo16_unsigned(int x) { return x & 0xffff; } + + protected: + + // Extract the top 32 bits in a 64 bit word. + static int32_t hi32(int64_t x) { + int32_t r = int32_t((uint64_t)x >> 32); + return r; + } + + public: + + static inline unsigned int align_addr(unsigned int addr, unsigned int a) { + return ((addr + (a - 1)) & ~(a - 1)); + } + + static inline bool is_aligned(unsigned int addr, unsigned int a) { + return (0 == addr % a); + } + + void flush() { + AbstractAssembler::flush(); + } + + inline void emit_int32(int); // shadows AbstractAssembler::emit_int32 + inline void emit_data(int); + inline void emit_data(int, RelocationHolder const&); + inline void emit_data(int, relocInfo::relocType rtype); + + // Emit an address. + inline address emit_addr(const address addr = NULL); + + // Emit a function descriptor with the specified entry point, TOC, + // and ENV. If the entry point is NULL, the descriptor will point + // just past the descriptor. + // Use values from friend functions as defaults. + inline address emit_fd(address entry = NULL, + address toc = (address) FunctionDescriptor::friend_toc, + address env = (address) FunctionDescriptor::friend_env); + + ///////////////////////////////////////////////////////////////////////////////////// + // PPC instructions + ///////////////////////////////////////////////////////////////////////////////////// + + // Memory instructions use r0 as hard coded 0, e.g. to simulate loading + // immediates. The normal instruction encoders enforce that r0 is not + // passed to them. Use either extended mnemonics encoders or the special ra0 + // versions. + + // Issue an illegal instruction. + inline void illtrap(); + static inline bool is_illtrap(int x); + + // PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions + inline void addi( Register d, Register a, int si16); + inline void addis(Register d, Register a, int si16); + private: + inline void addi_r0ok( Register d, Register a, int si16); + inline void addis_r0ok(Register d, Register a, int si16); + public: + inline void addic_( Register d, Register a, int si16); + inline void subfic( Register d, Register a, int si16); + inline void add( Register d, Register a, Register b); + inline void add_( Register d, Register a, Register b); + inline void subf( Register d, Register a, Register b); + inline void sub( Register d, Register a, Register b); + inline void subf_( Register d, Register a, Register b); + inline void addc( Register d, Register a, Register b); + inline void addc_( Register d, Register a, Register b); + inline void subfc( Register d, Register a, Register b); + inline void subfc_( Register d, Register a, Register b); + inline void adde( Register d, Register a, Register b); + inline void adde_( Register d, Register a, Register b); + inline void subfe( Register d, Register a, Register b); + inline void subfe_( Register d, Register a, Register b); + inline void neg( Register d, Register a); + inline void neg_( Register d, Register a); + inline void mulli( Register d, Register a, int si16); + inline void mulld( Register d, Register a, Register b); + inline void mulld_( Register d, Register a, Register b); + inline void mullw( Register d, Register a, Register b); + inline void mullw_( Register d, Register a, Register b); + inline void mulhw( Register d, Register a, Register b); + inline void mulhw_( Register d, Register a, Register b); + inline void mulhd( Register d, Register a, Register b); + inline void mulhd_( Register d, Register a, Register b); + inline void mulhdu( Register d, Register a, Register b); + inline void mulhdu_(Register d, Register a, Register b); + inline void divd( Register d, Register a, Register b); + inline void divd_( Register d, Register a, Register b); + inline void divw( Register d, Register a, Register b); + inline void divw_( Register d, Register a, Register b); + + // extended mnemonics + inline void li( Register d, int si16); + inline void lis( Register d, int si16); + inline void addir(Register d, int si16, Register a); + + static bool is_addi(int x) { + return ADDI_OPCODE == (x & ADDI_OPCODE_MASK); + } + static bool is_addis(int x) { + return ADDIS_OPCODE == (x & ADDIS_OPCODE_MASK); + } + static bool is_bxx(int x) { + return BXX_OPCODE == (x & BXX_OPCODE_MASK); + } + static bool is_b(int x) { + return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 0; + } + static bool is_bl(int x) { + return BXX_OPCODE == (x & BXX_OPCODE_MASK) && inv_lk_field(x) == 1; + } + static bool is_bcxx(int x) { + return BCXX_OPCODE == (x & BCXX_OPCODE_MASK); + } + static bool is_bxx_or_bcxx(int x) { + return is_bxx(x) || is_bcxx(x); + } + static bool is_bctrl(int x) { + return x == 0x4e800421; + } + static bool is_bctr(int x) { + return x == 0x4e800420; + } + static bool is_bclr(int x) { + return BCLR_OPCODE == (x & XL_FORM_OPCODE_MASK); + } + static bool is_li(int x) { + return is_addi(x) && inv_ra_field(x)==0; + } + static bool is_lis(int x) { + return is_addis(x) && inv_ra_field(x)==0; + } + static bool is_mtctr(int x) { + return MTCTR_OPCODE == (x & MTCTR_OPCODE_MASK); + } + static bool is_ld(int x) { + return LD_OPCODE == (x & LD_OPCODE_MASK); + } + static bool is_std(int x) { + return STD_OPCODE == (x & STD_OPCODE_MASK); + } + static bool is_stdu(int x) { + return STDU_OPCODE == (x & STDU_OPCODE_MASK); + } + static bool is_stdx(int x) { + return STDX_OPCODE == (x & STDX_OPCODE_MASK); + } + static bool is_stdux(int x) { + return STDUX_OPCODE == (x & STDUX_OPCODE_MASK); + } + static bool is_stwx(int x) { + return STWX_OPCODE == (x & STWX_OPCODE_MASK); + } + static bool is_stwux(int x) { + return STWUX_OPCODE == (x & STWUX_OPCODE_MASK); + } + static bool is_stw(int x) { + return STW_OPCODE == (x & STW_OPCODE_MASK); + } + static bool is_stwu(int x) { + return STWU_OPCODE == (x & STWU_OPCODE_MASK); + } + static bool is_ori(int x) { + return ORI_OPCODE == (x & ORI_OPCODE_MASK); + }; + static bool is_oris(int x) { + return ORIS_OPCODE == (x & ORIS_OPCODE_MASK); + }; + static bool is_rldicr(int x) { + return (RLDICR_OPCODE == (x & RLDICR_OPCODE_MASK)); + }; + static bool is_nop(int x) { + return x == 0x60000000; + } + // endgroup opcode for Power6 + static bool is_endgroup(int x) { + return is_ori(x) && inv_ra_field(x)==1 && inv_rs_field(x)==1 && inv_d1_field(x)==0; + } + + + private: + // PPC 1, section 3.3.9, Fixed-Point Compare Instructions + inline void cmpi( ConditionRegister bf, int l, Register a, int si16); + inline void cmp( ConditionRegister bf, int l, Register a, Register b); + inline void cmpli(ConditionRegister bf, int l, Register a, int ui16); + inline void cmpl( ConditionRegister bf, int l, Register a, Register b); + + public: + // extended mnemonics of Compare Instructions + inline void cmpwi( ConditionRegister crx, Register a, int si16); + inline void cmpdi( ConditionRegister crx, Register a, int si16); + inline void cmpw( ConditionRegister crx, Register a, Register b); + inline void cmpd( ConditionRegister crx, Register a, Register b); + inline void cmplwi(ConditionRegister crx, Register a, int ui16); + inline void cmpldi(ConditionRegister crx, Register a, int ui16); + inline void cmplw( ConditionRegister crx, Register a, Register b); + inline void cmpld( ConditionRegister crx, Register a, Register b); + + inline void isel( Register d, Register a, Register b, int bc); + + // PPC 1, section 3.3.11, Fixed-Point Logical Instructions + void andi( Register a, Register s, int ui16); // optimized version + inline void andi_( Register a, Register s, int ui16); + inline void andis_( Register a, Register s, int ui16); + inline void ori( Register a, Register s, int ui16); + inline void oris( Register a, Register s, int ui16); + inline void xori( Register a, Register s, int ui16); + inline void xoris( Register a, Register s, int ui16); + inline void andr( Register a, Register s, Register b); // suffixed by 'r' as 'and' is C++ keyword + inline void and_( Register a, Register s, Register b); + // Turn or0(rx,rx,rx) into a nop and avoid that we accidently emit a + // SMT-priority change instruction (see SMT instructions below). + inline void or_unchecked(Register a, Register s, Register b); + inline void orr( Register a, Register s, Register b); // suffixed by 'r' as 'or' is C++ keyword + inline void or_( Register a, Register s, Register b); + inline void xorr( Register a, Register s, Register b); // suffixed by 'r' as 'xor' is C++ keyword + inline void xor_( Register a, Register s, Register b); + inline void nand( Register a, Register s, Register b); + inline void nand_( Register a, Register s, Register b); + inline void nor( Register a, Register s, Register b); + inline void nor_( Register a, Register s, Register b); + inline void andc( Register a, Register s, Register b); + inline void andc_( Register a, Register s, Register b); + inline void orc( Register a, Register s, Register b); + inline void orc_( Register a, Register s, Register b); + inline void extsb( Register a, Register s); + inline void extsh( Register a, Register s); + inline void extsw( Register a, Register s); + + // extended mnemonics + inline void nop(); + // NOP for FP and BR units (different versions to allow them to be in one group) + inline void fpnop0(); + inline void fpnop1(); + inline void brnop0(); + inline void brnop1(); + inline void brnop2(); + + inline void mr( Register d, Register s); + inline void ori_opt( Register d, int ui16); + inline void oris_opt(Register d, int ui16); + + // endgroup opcode for Power6 + inline void endgroup(); + + // count instructions + inline void cntlzw( Register a, Register s); + inline void cntlzw_( Register a, Register s); + inline void cntlzd( Register a, Register s); + inline void cntlzd_( Register a, Register s); + + // PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions + inline void sld( Register a, Register s, Register b); + inline void sld_( Register a, Register s, Register b); + inline void slw( Register a, Register s, Register b); + inline void slw_( Register a, Register s, Register b); + inline void srd( Register a, Register s, Register b); + inline void srd_( Register a, Register s, Register b); + inline void srw( Register a, Register s, Register b); + inline void srw_( Register a, Register s, Register b); + inline void srad( Register a, Register s, Register b); + inline void srad_( Register a, Register s, Register b); + inline void sraw( Register a, Register s, Register b); + inline void sraw_( Register a, Register s, Register b); + inline void sradi( Register a, Register s, int sh6); + inline void sradi_( Register a, Register s, int sh6); + inline void srawi( Register a, Register s, int sh5); + inline void srawi_( Register a, Register s, int sh5); + + // extended mnemonics for Shift Instructions + inline void sldi( Register a, Register s, int sh6); + inline void sldi_( Register a, Register s, int sh6); + inline void slwi( Register a, Register s, int sh5); + inline void slwi_( Register a, Register s, int sh5); + inline void srdi( Register a, Register s, int sh6); + inline void srdi_( Register a, Register s, int sh6); + inline void srwi( Register a, Register s, int sh5); + inline void srwi_( Register a, Register s, int sh5); + + inline void clrrdi( Register a, Register s, int ui6); + inline void clrrdi_( Register a, Register s, int ui6); + inline void clrldi( Register a, Register s, int ui6); + inline void clrldi_( Register a, Register s, int ui6); + inline void clrlsldi(Register a, Register s, int clrl6, int shl6); + inline void clrlsldi_(Register a, Register s, int clrl6, int shl6); + inline void extrdi( Register a, Register s, int n, int b); + // testbit with condition register + inline void testbitdi(ConditionRegister cr, Register a, Register s, int ui6); + + // rotate instructions + inline void rotldi( Register a, Register s, int n); + inline void rotrdi( Register a, Register s, int n); + inline void rotlwi( Register a, Register s, int n); + inline void rotrwi( Register a, Register s, int n); + + // Rotate Instructions + inline void rldic( Register a, Register s, int sh6, int mb6); + inline void rldic_( Register a, Register s, int sh6, int mb6); + inline void rldicr( Register a, Register s, int sh6, int mb6); + inline void rldicr_( Register a, Register s, int sh6, int mb6); + inline void rldicl( Register a, Register s, int sh6, int mb6); + inline void rldicl_( Register a, Register s, int sh6, int mb6); + inline void rlwinm( Register a, Register s, int sh5, int mb5, int me5); + inline void rlwinm_( Register a, Register s, int sh5, int mb5, int me5); + inline void rldimi( Register a, Register s, int sh6, int mb6); + inline void rldimi_( Register a, Register s, int sh6, int mb6); + inline void rlwimi( Register a, Register s, int sh5, int mb5, int me5); + inline void insrdi( Register a, Register s, int n, int b); + inline void insrwi( Register a, Register s, int n, int b); + + // PPC 1, section 3.3.2 Fixed-Point Load Instructions + // 4 bytes + inline void lwzx( Register d, Register s1, Register s2); + inline void lwz( Register d, int si16, Register s1); + inline void lwzu( Register d, int si16, Register s1); + + // 4 bytes + inline void lwax( Register d, Register s1, Register s2); + inline void lwa( Register d, int si16, Register s1); + + // 2 bytes + inline void lhzx( Register d, Register s1, Register s2); + inline void lhz( Register d, int si16, Register s1); + inline void lhzu( Register d, int si16, Register s1); + + // 2 bytes + inline void lhax( Register d, Register s1, Register s2); + inline void lha( Register d, int si16, Register s1); + inline void lhau( Register d, int si16, Register s1); + + // 1 byte + inline void lbzx( Register d, Register s1, Register s2); + inline void lbz( Register d, int si16, Register s1); + inline void lbzu( Register d, int si16, Register s1); + + // 8 bytes + inline void ldx( Register d, Register s1, Register s2); + inline void ld( Register d, int si16, Register s1); + inline void ldu( Register d, int si16, Register s1); + + // PPC 1, section 3.3.3 Fixed-Point Store Instructions + inline void stwx( Register d, Register s1, Register s2); + inline void stw( Register d, int si16, Register s1); + inline void stwu( Register d, int si16, Register s1); + + inline void sthx( Register d, Register s1, Register s2); + inline void sth( Register d, int si16, Register s1); + inline void sthu( Register d, int si16, Register s1); + + inline void stbx( Register d, Register s1, Register s2); + inline void stb( Register d, int si16, Register s1); + inline void stbu( Register d, int si16, Register s1); + + inline void stdx( Register d, Register s1, Register s2); + inline void std( Register d, int si16, Register s1); + inline void stdu( Register d, int si16, Register s1); + inline void stdux(Register s, Register a, Register b); + + // PPC 1, section 3.3.13 Move To/From System Register Instructions + inline void mtlr( Register s1); + inline void mflr( Register d); + inline void mtctr(Register s1); + inline void mfctr(Register d); + inline void mtcrf(int fxm, Register s); + inline void mfcr( Register d); + inline void mcrf( ConditionRegister crd, ConditionRegister cra); + inline void mtcr( Register s); + + // PPC 1, section 2.4.1 Branch Instructions + inline void b( address a, relocInfo::relocType rt = relocInfo::none); + inline void b( Label& L); + inline void bl( address a, relocInfo::relocType rt = relocInfo::none); + inline void bl( Label& L); + inline void bc( int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); + inline void bc( int boint, int biint, Label& L); + inline void bcl(int boint, int biint, address a, relocInfo::relocType rt = relocInfo::none); + inline void bcl(int boint, int biint, Label& L); + + inline void bclr( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); + inline void bclrl( int boint, int biint, int bhint, relocInfo::relocType rt = relocInfo::none); + inline void bcctr( int boint, int biint, int bhint = bhintbhBCCTRisNotReturnButSame, + relocInfo::relocType rt = relocInfo::none); + inline void bcctrl(int boint, int biint, int bhint = bhintbhBCLRisReturn, + relocInfo::relocType rt = relocInfo::none); + + // helper function for b, bcxx + inline bool is_within_range_of_b(address a, address pc); + inline bool is_within_range_of_bcxx(address a, address pc); + + // get the destination of a bxx branch (b, bl, ba, bla) + static inline address bxx_destination(address baddr); + static inline address bxx_destination(int instr, address pc); + static inline intptr_t bxx_destination_offset(int instr, intptr_t bxx_pos); + + // extended mnemonics for branch instructions + inline void blt(ConditionRegister crx, Label& L); + inline void bgt(ConditionRegister crx, Label& L); + inline void beq(ConditionRegister crx, Label& L); + inline void bso(ConditionRegister crx, Label& L); + inline void bge(ConditionRegister crx, Label& L); + inline void ble(ConditionRegister crx, Label& L); + inline void bne(ConditionRegister crx, Label& L); + inline void bns(ConditionRegister crx, Label& L); + + // Branch instructions with static prediction hints. + inline void blt_predict_taken( ConditionRegister crx, Label& L); + inline void bgt_predict_taken( ConditionRegister crx, Label& L); + inline void beq_predict_taken( ConditionRegister crx, Label& L); + inline void bso_predict_taken( ConditionRegister crx, Label& L); + inline void bge_predict_taken( ConditionRegister crx, Label& L); + inline void ble_predict_taken( ConditionRegister crx, Label& L); + inline void bne_predict_taken( ConditionRegister crx, Label& L); + inline void bns_predict_taken( ConditionRegister crx, Label& L); + inline void blt_predict_not_taken(ConditionRegister crx, Label& L); + inline void bgt_predict_not_taken(ConditionRegister crx, Label& L); + inline void beq_predict_not_taken(ConditionRegister crx, Label& L); + inline void bso_predict_not_taken(ConditionRegister crx, Label& L); + inline void bge_predict_not_taken(ConditionRegister crx, Label& L); + inline void ble_predict_not_taken(ConditionRegister crx, Label& L); + inline void bne_predict_not_taken(ConditionRegister crx, Label& L); + inline void bns_predict_not_taken(ConditionRegister crx, Label& L); + + // for use in conjunction with testbitdi: + inline void btrue( ConditionRegister crx, Label& L); + inline void bfalse(ConditionRegister crx, Label& L); + + inline void bltl(ConditionRegister crx, Label& L); + inline void bgtl(ConditionRegister crx, Label& L); + inline void beql(ConditionRegister crx, Label& L); + inline void bsol(ConditionRegister crx, Label& L); + inline void bgel(ConditionRegister crx, Label& L); + inline void blel(ConditionRegister crx, Label& L); + inline void bnel(ConditionRegister crx, Label& L); + inline void bnsl(ConditionRegister crx, Label& L); + + // extended mnemonics for Branch Instructions via LR + // We use `blr' for returns. + inline void blr(relocInfo::relocType rt = relocInfo::none); + + // extended mnemonics for Branch Instructions with CTR + // bdnz means `decrement CTR and jump to L if CTR is not zero' + inline void bdnz(Label& L); + // Decrement and branch if result is zero. + inline void bdz(Label& L); + // we use `bctr[l]' for jumps/calls in function descriptor glue + // code, e.g. calls to runtime functions + inline void bctr( relocInfo::relocType rt = relocInfo::none); + inline void bctrl(relocInfo::relocType rt = relocInfo::none); + // conditional jumps/branches via CTR + inline void beqctr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); + inline void beqctrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); + inline void bnectr( ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); + inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none); + + // condition register logic instructions + inline void crand( int d, int s1, int s2); + inline void crnand(int d, int s1, int s2); + inline void cror( int d, int s1, int s2); + inline void crxor( int d, int s1, int s2); + inline void crnor( int d, int s1, int s2); + inline void creqv( int d, int s1, int s2); + inline void crandc(int d, int s1, int s2); + inline void crorc( int d, int s1, int s2); + + // icache and dcache related instructions + inline void icbi( Register s1, Register s2); + //inline void dcba(Register s1, Register s2); // Instruction for embedded processor only. + inline void dcbz( Register s1, Register s2); + inline void dcbst( Register s1, Register s2); + inline void dcbf( Register s1, Register s2); + + enum ct_cache_specification { + ct_primary_cache = 0, + ct_secondary_cache = 2 + }; + // dcache read hint + inline void dcbt( Register s1, Register s2); + inline void dcbtct( Register s1, Register s2, int ct); + inline void dcbtds( Register s1, Register s2, int ds); + // dcache write hint + inline void dcbtst( Register s1, Register s2); + inline void dcbtstct(Register s1, Register s2, int ct); + + // machine barrier instructions: + // + // - sync two-way memory barrier, aka fence + // - lwsync orders Store|Store, + // Load|Store, + // Load|Load, + // but not Store|Load + // - eieio orders memory accesses for device memory (only) + // - isync invalidates speculatively executed instructions + // From the Power ISA 2.06 documentation: + // "[...] an isync instruction prevents the execution of + // instructions following the isync until instructions + // preceding the isync have completed, [...]" + // From IBM's AIX assembler reference: + // "The isync [...] instructions causes the processor to + // refetch any instructions that might have been fetched + // prior to the isync instruction. The instruction isync + // causes the processor to wait for all previous instructions + // to complete. Then any instructions already fetched are + // discarded and instruction processing continues in the + // environment established by the previous instructions." + // + // semantic barrier instructions: + // (as defined in orderAccess.hpp) + // + // - release orders Store|Store, (maps to lwsync) + // Load|Store + // - acquire orders Load|Store, (maps to lwsync) + // Load|Load + // - fence orders Store|Store, (maps to sync) + // Load|Store, + // Load|Load, + // Store|Load + // + private: + inline void sync(int l); + public: + inline void sync(); + inline void lwsync(); + inline void ptesync(); + inline void eieio(); + inline void isync(); + + inline void release(); + inline void acquire(); + inline void fence(); + + // atomics + inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0); + inline void ldarx_unchecked(Register d, Register a, Register b, int eh1 = 0); + inline bool lxarx_hint_exclusive_access(); + inline void lwarx( Register d, Register a, Register b, bool hint_exclusive_access = false); + inline void ldarx( Register d, Register a, Register b, bool hint_exclusive_access = false); + inline void stwcx_( Register s, Register a, Register b); + inline void stdcx_( Register s, Register a, Register b); + + // Instructions for adjusting thread priority for simultaneous + // multithreading (SMT) on Power5. + private: + inline void smt_prio_very_low(); + inline void smt_prio_medium_high(); + inline void smt_prio_high(); + + public: + inline void smt_prio_low(); + inline void smt_prio_medium_low(); + inline void smt_prio_medium(); + + // trap instructions + inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur) + // NOT FOR DIRECT USE!! + protected: + inline void tdi_unchecked(int tobits, Register a, int si16); + inline void twi_unchecked(int tobits, Register a, int si16); + inline void tdi( int tobits, Register a, int si16); // asserts UseSIGTRAP + inline void twi( int tobits, Register a, int si16); // asserts UseSIGTRAP + inline void td( int tobits, Register a, Register b); // asserts UseSIGTRAP + inline void tw( int tobits, Register a, Register b); // asserts UseSIGTRAP + + static bool is_tdi(int x, int tobits, int ra, int si16) { + return (TDI_OPCODE == (x & TDI_OPCODE_MASK)) + && (tobits == inv_to_field(x)) + && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) + && (si16 == inv_si_field(x)); + } + + static bool is_twi(int x, int tobits, int ra, int si16) { + return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) + && (tobits == inv_to_field(x)) + && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) + && (si16 == inv_si_field(x)); + } + + static bool is_twi(int x, int tobits, int ra) { + return (TWI_OPCODE == (x & TWI_OPCODE_MASK)) + && (tobits == inv_to_field(x)) + && (ra == -1/*any reg*/ || ra == inv_ra_field(x)); + } + + static bool is_td(int x, int tobits, int ra, int rb) { + return (TD_OPCODE == (x & TD_OPCODE_MASK)) + && (tobits == inv_to_field(x)) + && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) + && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); + } + + static bool is_tw(int x, int tobits, int ra, int rb) { + return (TW_OPCODE == (x & TW_OPCODE_MASK)) + && (tobits == inv_to_field(x)) + && (ra == -1/*any reg*/ || ra == inv_ra_field(x)) + && (rb == -1/*any reg*/ || rb == inv_rb_field(x)); + } + + public: + // PPC floating point instructions + // PPC 1, section 4.6.2 Floating-Point Load Instructions + inline void lfs( FloatRegister d, int si16, Register a); + inline void lfsu( FloatRegister d, int si16, Register a); + inline void lfsx( FloatRegister d, Register a, Register b); + inline void lfd( FloatRegister d, int si16, Register a); + inline void lfdu( FloatRegister d, int si16, Register a); + inline void lfdx( FloatRegister d, Register a, Register b); + + // PPC 1, section 4.6.3 Floating-Point Store Instructions + inline void stfs( FloatRegister s, int si16, Register a); + inline void stfsu( FloatRegister s, int si16, Register a); + inline void stfsx( FloatRegister s, Register a, Register b); + inline void stfd( FloatRegister s, int si16, Register a); + inline void stfdu( FloatRegister s, int si16, Register a); + inline void stfdx( FloatRegister s, Register a, Register b); + + // PPC 1, section 4.6.4 Floating-Point Move Instructions + inline void fmr( FloatRegister d, FloatRegister b); + inline void fmr_( FloatRegister d, FloatRegister b); + + // inline void mffgpr( FloatRegister d, Register b); + // inline void mftgpr( Register d, FloatRegister b); + inline void cmpb( Register a, Register s, Register b); + inline void popcntb(Register a, Register s); + inline void popcntw(Register a, Register s); + inline void popcntd(Register a, Register s); + + inline void fneg( FloatRegister d, FloatRegister b); + inline void fneg_( FloatRegister d, FloatRegister b); + inline void fabs( FloatRegister d, FloatRegister b); + inline void fabs_( FloatRegister d, FloatRegister b); + inline void fnabs( FloatRegister d, FloatRegister b); + inline void fnabs_(FloatRegister d, FloatRegister b); + + // PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic Instructions + inline void fadd( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fadd_( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fadds( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fadds_(FloatRegister d, FloatRegister a, FloatRegister b); + inline void fsub( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fsub_( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fsubs( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fsubs_(FloatRegister d, FloatRegister a, FloatRegister b); + inline void fmul( FloatRegister d, FloatRegister a, FloatRegister c); + inline void fmul_( FloatRegister d, FloatRegister a, FloatRegister c); + inline void fmuls( FloatRegister d, FloatRegister a, FloatRegister c); + inline void fmuls_(FloatRegister d, FloatRegister a, FloatRegister c); + inline void fdiv( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fdiv_( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b); + inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b); + + // PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions + inline void frsp( FloatRegister d, FloatRegister b); + inline void fctid( FloatRegister d, FloatRegister b); + inline void fctidz(FloatRegister d, FloatRegister b); + inline void fctiw( FloatRegister d, FloatRegister b); + inline void fctiwz(FloatRegister d, FloatRegister b); + inline void fcfid( FloatRegister d, FloatRegister b); + inline void fcfids(FloatRegister d, FloatRegister b); + + // PPC 1, section 4.6.7 Floating-Point Compare Instructions + inline void fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b); + + inline void fsqrt( FloatRegister d, FloatRegister b); + inline void fsqrts(FloatRegister d, FloatRegister b); + + // Vector instructions for >= Power6. + inline void lvebx( VectorRegister d, Register s1, Register s2); + inline void lvehx( VectorRegister d, Register s1, Register s2); + inline void lvewx( VectorRegister d, Register s1, Register s2); + inline void lvx( VectorRegister d, Register s1, Register s2); + inline void lvxl( VectorRegister d, Register s1, Register s2); + inline void stvebx( VectorRegister d, Register s1, Register s2); + inline void stvehx( VectorRegister d, Register s1, Register s2); + inline void stvewx( VectorRegister d, Register s1, Register s2); + inline void stvx( VectorRegister d, Register s1, Register s2); + inline void stvxl( VectorRegister d, Register s1, Register s2); + inline void lvsl( VectorRegister d, Register s1, Register s2); + inline void lvsr( VectorRegister d, Register s1, Register s2); + inline void vpkpx( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkshss( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkswss( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkshus( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkswus( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkuhum( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkuwum( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkuhus( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpkuwus( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vupkhpx( VectorRegister d, VectorRegister b); + inline void vupkhsb( VectorRegister d, VectorRegister b); + inline void vupkhsh( VectorRegister d, VectorRegister b); + inline void vupklpx( VectorRegister d, VectorRegister b); + inline void vupklsb( VectorRegister d, VectorRegister b); + inline void vupklsh( VectorRegister d, VectorRegister b); + inline void vmrghb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmrghw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmrghh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmrglb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmrglw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmrglh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsplt( VectorRegister d, int ui4, VectorRegister b); + inline void vsplth( VectorRegister d, int ui3, VectorRegister b); + inline void vspltw( VectorRegister d, int ui2, VectorRegister b); + inline void vspltisb( VectorRegister d, int si5); + inline void vspltish( VectorRegister d, int si5); + inline void vspltisw( VectorRegister d, int si5); + inline void vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vsl( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4); + inline void vslo( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsr( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsro( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddcuw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddshs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddsbs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddsws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddubm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vadduwm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vadduhm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddubs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vadduws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vadduhs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubcuw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubshs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubsbs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubsws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsububm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubuwm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubuhm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsububs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubuws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsubuhs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmulesb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmuleub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmulesh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmuleuh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmulosb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmuloub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmulosh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmulouh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmhaddshs(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmhraddshs(VectorRegister d,VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmladduhm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsubuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsummbm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsumshm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsumshs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsumuhm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vmsumuhs( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + inline void vsumsws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsum2sws( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsum4sbs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsum4ubs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsum4shs( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavgsb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavgsw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavgsh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavgub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavguw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vavguh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxsb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxsw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxsh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxuw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmaxuh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminsb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminsw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminsh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminuw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vminuh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtub( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtuh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtuw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequb_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequh_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpequw_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsh_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsb_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtsw_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtub_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtuh_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcmpgtuw_(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vand( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vandc( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vnor( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vor( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vxor( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vrlb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vrlw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vrlh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vslb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vskw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vslh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsrb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsrw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsrh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsrab( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsraw( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsrah( VectorRegister d, VectorRegister a, VectorRegister b); + // Vector Floating-Point not implemented yet + inline void mtvscr( VectorRegister b); + inline void mfvscr( VectorRegister d); + + // The following encoders use r0 as second operand. These instructions + // read r0 as '0'. + inline void lwzx( Register d, Register s2); + inline void lwz( Register d, int si16); + inline void lwax( Register d, Register s2); + inline void lwa( Register d, int si16); + inline void lhzx( Register d, Register s2); + inline void lhz( Register d, int si16); + inline void lhax( Register d, Register s2); + inline void lha( Register d, int si16); + inline void lbzx( Register d, Register s2); + inline void lbz( Register d, int si16); + inline void ldx( Register d, Register s2); + inline void ld( Register d, int si16); + inline void stwx( Register d, Register s2); + inline void stw( Register d, int si16); + inline void sthx( Register d, Register s2); + inline void sth( Register d, int si16); + inline void stbx( Register d, Register s2); + inline void stb( Register d, int si16); + inline void stdx( Register d, Register s2); + inline void std( Register d, int si16); + + // PPC 2, section 3.2.1 Instruction Cache Instructions + inline void icbi( Register s2); + // PPC 2, section 3.2.2 Data Cache Instructions + //inlinevoid dcba( Register s2); // Instruction for embedded processor only. + inline void dcbz( Register s2); + inline void dcbst( Register s2); + inline void dcbf( Register s2); + // dcache read hint + inline void dcbt( Register s2); + inline void dcbtct( Register s2, int ct); + inline void dcbtds( Register s2, int ds); + // dcache write hint + inline void dcbtst( Register s2); + inline void dcbtstct(Register s2, int ct); + + // Atomics: use ra0mem to disallow R0 as base. + inline void lwarx_unchecked(Register d, Register b, int eh1); + inline void ldarx_unchecked(Register d, Register b, int eh1); + inline void lwarx( Register d, Register b, bool hint_exclusive_access); + inline void ldarx( Register d, Register b, bool hint_exclusive_access); + inline void stwcx_(Register s, Register b); + inline void stdcx_(Register s, Register b); + inline void lfs( FloatRegister d, int si16); + inline void lfsx( FloatRegister d, Register b); + inline void lfd( FloatRegister d, int si16); + inline void lfdx( FloatRegister d, Register b); + inline void stfs( FloatRegister s, int si16); + inline void stfsx( FloatRegister s, Register b); + inline void stfd( FloatRegister s, int si16); + inline void stfdx( FloatRegister s, Register b); + inline void lvebx( VectorRegister d, Register s2); + inline void lvehx( VectorRegister d, Register s2); + inline void lvewx( VectorRegister d, Register s2); + inline void lvx( VectorRegister d, Register s2); + inline void lvxl( VectorRegister d, Register s2); + inline void stvebx(VectorRegister d, Register s2); + inline void stvehx(VectorRegister d, Register s2); + inline void stvewx(VectorRegister d, Register s2); + inline void stvx( VectorRegister d, Register s2); + inline void stvxl( VectorRegister d, Register s2); + inline void lvsl( VectorRegister d, Register s2); + inline void lvsr( VectorRegister d, Register s2); + + // RegisterOrConstant versions. + // These emitters choose between the versions using two registers and + // those with register and immediate, depending on the content of roc. + // If the constant is not encodable as immediate, instructions to + // load the constant are emitted beforehand. Store instructions need a + // tmp reg if the constant is not encodable as immediate. + // Size unpredictable. + void ld( Register d, RegisterOrConstant roc, Register s1 = noreg); + void lwa( Register d, RegisterOrConstant roc, Register s1 = noreg); + void lwz( Register d, RegisterOrConstant roc, Register s1 = noreg); + void lha( Register d, RegisterOrConstant roc, Register s1 = noreg); + void lhz( Register d, RegisterOrConstant roc, Register s1 = noreg); + void lbz( Register d, RegisterOrConstant roc, Register s1 = noreg); + void std( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); + void stw( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); + void sth( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); + void stb( Register d, RegisterOrConstant roc, Register s1 = noreg, Register tmp = noreg); + void add( Register d, RegisterOrConstant roc, Register s1); + void subf(Register d, RegisterOrConstant roc, Register s1); + void cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1); + + + // Emit several instructions to load a 64 bit constant. This issues a fixed + // instruction pattern so that the constant can be patched later on. + enum { + load_const_size = 5 * BytesPerInstWord + }; + void load_const(Register d, long a, Register tmp = noreg); + inline void load_const(Register d, void* a, Register tmp = noreg); + inline void load_const(Register d, Label& L, Register tmp = noreg); + inline void load_const(Register d, AddressLiteral& a, Register tmp = noreg); + + // Load a 64 bit constant, optimized, not identifyable. + // Tmp can be used to increase ILP. Set return_simm16_rest=true to get a + // 16 bit immediate offset. This is useful if the offset can be encoded in + // a succeeding instruction. + int load_const_optimized(Register d, long a, Register tmp = noreg, bool return_simm16_rest = false); + inline int load_const_optimized(Register d, void* a, Register tmp = noreg, bool return_simm16_rest = false) { + return load_const_optimized(d, (long)(unsigned long)a, tmp, return_simm16_rest); + } + + // Creation + Assembler(CodeBuffer* code) : AbstractAssembler(code) { +#ifdef CHECK_DELAY + delay_state = no_delay; +#endif + } + + // Testing +#ifndef PRODUCT + void test_asm(); +#endif +}; + + +#endif // CPU_PPC_VM_ASSEMBLER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp new file mode 100644 index 00000000000..a1277b8cdbb --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -0,0 +1,792 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_ASSEMBLER_PPC_INLINE_HPP +#define CPU_PPC_VM_ASSEMBLER_PPC_INLINE_HPP + +#include "asm/assembler.inline.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + +inline void Assembler::emit_int32(int x) { + AbstractAssembler::emit_int32(x); +} + +inline void Assembler::emit_data(int x) { + emit_int32(x); +} + +inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { + relocate(rtype); + emit_int32(x); +} + +inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { + relocate(rspec); + emit_int32(x); +} + +// Emit an address +inline address Assembler::emit_addr(const address addr) { + address start = pc(); + emit_address(addr); + return start; +} + +// Emit a function descriptor with the specified entry point, TOC, and +// ENV. If the entry point is NULL, the descriptor will point just +// past the descriptor. +inline address Assembler::emit_fd(address entry, address toc, address env) { + FunctionDescriptor* fd = (FunctionDescriptor*)pc(); + + assert(sizeof(FunctionDescriptor) == 3*sizeof(address), "function descriptor size"); + + (void)emit_addr(); + (void)emit_addr(); + (void)emit_addr(); + + fd->set_entry(entry == NULL ? pc() : entry); + fd->set_toc(toc); + fd->set_env(env); + + return (address)fd; +} + +// Issue an illegal instruction. 0 is guaranteed to be an illegal instruction. +inline void Assembler::illtrap() { Assembler::emit_int32(0); } +inline bool Assembler::is_illtrap(int x) { return x == 0; } + +// PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions +inline void Assembler::addi( Register d, Register a, int si16) { assert(a != R0, "r0 not allowed"); addi_r0ok( d, a, si16); } +inline void Assembler::addis( Register d, Register a, int si16) { assert(a != R0, "r0 not allowed"); addis_r0ok(d, a, si16); } +inline void Assembler::addi_r0ok(Register d,Register a,int si16) { emit_int32(ADDI_OPCODE | rt(d) | ra(a) | simm(si16, 16)); } +inline void Assembler::addis_r0ok(Register d,Register a,int si16) { emit_int32(ADDIS_OPCODE | rt(d) | ra(a) | simm(si16, 16)); } +inline void Assembler::addic_( Register d, Register a, int si16) { emit_int32(ADDIC__OPCODE | rt(d) | ra(a) | simm(si16, 16)); } +inline void Assembler::subfic( Register d, Register a, int si16) { emit_int32(SUBFIC_OPCODE | rt(d) | ra(a) | simm(si16, 16)); } +inline void Assembler::add( Register d, Register a, Register b) { emit_int32(ADD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::add_( Register d, Register a, Register b) { emit_int32(ADD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::subf( Register d, Register a, Register b) { emit_int32(SUBF_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::sub( Register d, Register a, Register b) { subf(d, b, a); } +inline void Assembler::subf_( Register d, Register a, Register b) { emit_int32(SUBF_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::addc( Register d, Register a, Register b) { emit_int32(ADDC_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::addc_( Register d, Register a, Register b) { emit_int32(ADDC_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::subfc( Register d, Register a, Register b) { emit_int32(SUBFC_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::subfc_( Register d, Register a, Register b) { emit_int32(SUBFC_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::adde( Register d, Register a, Register b) { emit_int32(ADDE_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::adde_( Register d, Register a, Register b) { emit_int32(ADDE_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::subfe( Register d, Register a, Register b) { emit_int32(SUBFE_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::subfe_( Register d, Register a, Register b) { emit_int32(SUBFE_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::neg( Register d, Register a) { emit_int32(NEG_OPCODE | rt(d) | ra(a) | oe(0) | rc(0)); } +inline void Assembler::neg_( Register d, Register a) { emit_int32(NEG_OPCODE | rt(d) | ra(a) | oe(0) | rc(1)); } +inline void Assembler::mulli( Register d, Register a, int si16) { emit_int32(MULLI_OPCODE | rt(d) | ra(a) | simm(si16, 16)); } +inline void Assembler::mulld( Register d, Register a, Register b) { emit_int32(MULLD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::mulld_( Register d, Register a, Register b) { emit_int32(MULLD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::mullw( Register d, Register a, Register b) { emit_int32(MULLW_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::mullw_( Register d, Register a, Register b) { emit_int32(MULLW_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::mulhw( Register d, Register a, Register b) { emit_int32(MULHW_OPCODE | rt(d) | ra(a) | rb(b) | rc(0)); } +inline void Assembler::mulhw_( Register d, Register a, Register b) { emit_int32(MULHW_OPCODE | rt(d) | ra(a) | rb(b) | rc(1)); } +inline void Assembler::mulhd( Register d, Register a, Register b) { emit_int32(MULHD_OPCODE | rt(d) | ra(a) | rb(b) | rc(0)); } +inline void Assembler::mulhd_( Register d, Register a, Register b) { emit_int32(MULHD_OPCODE | rt(d) | ra(a) | rb(b) | rc(1)); } +inline void Assembler::mulhdu( Register d, Register a, Register b) { emit_int32(MULHDU_OPCODE | rt(d) | ra(a) | rb(b) | rc(0)); } +inline void Assembler::mulhdu_(Register d, Register a, Register b) { emit_int32(MULHDU_OPCODE | rt(d) | ra(a) | rb(b) | rc(1)); } +inline void Assembler::divd( Register d, Register a, Register b) { emit_int32(DIVD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::divd_( Register d, Register a, Register b) { emit_int32(DIVD_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } +inline void Assembler::divw( Register d, Register a, Register b) { emit_int32(DIVW_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(0)); } +inline void Assembler::divw_( Register d, Register a, Register b) { emit_int32(DIVW_OPCODE | rt(d) | ra(a) | rb(b) | oe(0) | rc(1)); } + +// extended mnemonics +inline void Assembler::li( Register d, int si16) { Assembler::addi_r0ok( d, R0, si16); } +inline void Assembler::lis( Register d, int si16) { Assembler::addis_r0ok(d, R0, si16); } +inline void Assembler::addir(Register d, int si16, Register a) { Assembler::addi(d, a, si16); } + +// PPC 1, section 3.3.9, Fixed-Point Compare Instructions +inline void Assembler::cmpi( ConditionRegister f, int l, Register a, int si16) { emit_int32( CMPI_OPCODE | bf(f) | l10(l) | ra(a) | simm(si16,16)); } +inline void Assembler::cmp( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMP_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } +inline void Assembler::cmpli( ConditionRegister f, int l, Register a, int ui16) { emit_int32( CMPLI_OPCODE | bf(f) | l10(l) | ra(a) | uimm(ui16,16)); } +inline void Assembler::cmpl( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPL_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } + +// extended mnemonics of Compare Instructions +inline void Assembler::cmpwi( ConditionRegister crx, Register a, int si16) { Assembler::cmpi( crx, 0, a, si16); } +inline void Assembler::cmpdi( ConditionRegister crx, Register a, int si16) { Assembler::cmpi( crx, 1, a, si16); } +inline void Assembler::cmpw( ConditionRegister crx, Register a, Register b) { Assembler::cmp( crx, 0, a, b); } +inline void Assembler::cmpd( ConditionRegister crx, Register a, Register b) { Assembler::cmp( crx, 1, a, b); } +inline void Assembler::cmplwi(ConditionRegister crx, Register a, int ui16) { Assembler::cmpli(crx, 0, a, ui16); } +inline void Assembler::cmpldi(ConditionRegister crx, Register a, int ui16) { Assembler::cmpli(crx, 1, a, ui16); } +inline void Assembler::cmplw( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 0, a, b); } +inline void Assembler::cmpld( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 1, a, b); } + +inline void Assembler::isel(Register d, Register a, Register b, int c) { emit_int32(ISEL_OPCODE | rt(d) | ra(a) | rb(b) | bc(c)); } + +// PPC 1, section 3.3.11, Fixed-Point Logical Instructions +inline void Assembler::andi_( Register a, Register s, int ui16) { emit_int32(ANDI_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::andis_( Register a, Register s, int ui16) { emit_int32(ANDIS_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::ori( Register a, Register s, int ui16) { emit_int32(ORI_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::oris( Register a, Register s, int ui16) { emit_int32(ORIS_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::xori( Register a, Register s, int ui16) { emit_int32(XORI_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::xoris( Register a, Register s, int ui16) { emit_int32(XORIS_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } +inline void Assembler::andr( Register a, Register s, Register b) { emit_int32(AND_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::and_( Register a, Register s, Register b) { emit_int32(AND_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } + +inline void Assembler::or_unchecked(Register a, Register s, Register b){ emit_int32(OR_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::orr( Register a, Register s, Register b) { if (a==s && s==b) { Assembler::nop(); } else { Assembler::or_unchecked(a,s,b); } } +inline void Assembler::or_( Register a, Register s, Register b) { emit_int32(OR_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::xorr( Register a, Register s, Register b) { emit_int32(XOR_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::xor_( Register a, Register s, Register b) { emit_int32(XOR_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::nand( Register a, Register s, Register b) { emit_int32(NAND_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::nand_( Register a, Register s, Register b) { emit_int32(NAND_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::nor( Register a, Register s, Register b) { emit_int32(NOR_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::nor_( Register a, Register s, Register b) { emit_int32(NOR_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::andc( Register a, Register s, Register b) { emit_int32(ANDC_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::andc_( Register a, Register s, Register b) { emit_int32(ANDC_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::orc( Register a, Register s, Register b) { emit_int32(ORC_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::orc_( Register a, Register s, Register b) { emit_int32(ORC_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::extsb( Register a, Register s) { emit_int32(EXTSB_OPCODE | rta(a) | rs(s) | rc(0)); } +inline void Assembler::extsh( Register a, Register s) { emit_int32(EXTSH_OPCODE | rta(a) | rs(s) | rc(0)); } +inline void Assembler::extsw( Register a, Register s) { emit_int32(EXTSW_OPCODE | rta(a) | rs(s) | rc(0)); } + +// extended mnemonics +inline void Assembler::nop() { Assembler::ori(R0, R0, 0); } +// NOP for FP and BR units (different versions to allow them to be in one group) +inline void Assembler::fpnop0() { Assembler::fmr(F30, F30); } +inline void Assembler::fpnop1() { Assembler::fmr(F31, F31); } +inline void Assembler::brnop0() { Assembler::mcrf(CCR2, CCR2); } +inline void Assembler::brnop1() { Assembler::mcrf(CCR3, CCR3); } +inline void Assembler::brnop2() { Assembler::mcrf(CCR4, CCR4); } + +inline void Assembler::mr( Register d, Register s) { Assembler::orr(d, s, s); } +inline void Assembler::ori_opt( Register d, int ui16) { if (ui16!=0) Assembler::ori( d, d, ui16); } +inline void Assembler::oris_opt(Register d, int ui16) { if (ui16!=0) Assembler::oris(d, d, ui16); } + +inline void Assembler::endgroup() { Assembler::ori(R1, R1, 0); } + +// count instructions +inline void Assembler::cntlzw( Register a, Register s) { emit_int32(CNTLZW_OPCODE | rta(a) | rs(s) | rc(0)); } +inline void Assembler::cntlzw_( Register a, Register s) { emit_int32(CNTLZW_OPCODE | rta(a) | rs(s) | rc(1)); } +inline void Assembler::cntlzd( Register a, Register s) { emit_int32(CNTLZD_OPCODE | rta(a) | rs(s) | rc(0)); } +inline void Assembler::cntlzd_( Register a, Register s) { emit_int32(CNTLZD_OPCODE | rta(a) | rs(s) | rc(1)); } + +// PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions +inline void Assembler::sld( Register a, Register s, Register b) { emit_int32(SLD_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::sld_( Register a, Register s, Register b) { emit_int32(SLD_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::slw( Register a, Register s, Register b) { emit_int32(SLW_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::slw_( Register a, Register s, Register b) { emit_int32(SLW_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::srd( Register a, Register s, Register b) { emit_int32(SRD_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::srd_( Register a, Register s, Register b) { emit_int32(SRD_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::srw( Register a, Register s, Register b) { emit_int32(SRW_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::srw_( Register a, Register s, Register b) { emit_int32(SRW_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::srad( Register a, Register s, Register b) { emit_int32(SRAD_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::srad_( Register a, Register s, Register b) { emit_int32(SRAD_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::sraw( Register a, Register s, Register b) { emit_int32(SRAW_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::sraw_( Register a, Register s, Register b) { emit_int32(SRAW_OPCODE | rta(a) | rs(s) | rb(b) | rc(1)); } +inline void Assembler::sradi( Register a, Register s, int sh6) { emit_int32(SRADI_OPCODE | rta(a) | rs(s) | sh162030(sh6) | rc(0)); } +inline void Assembler::sradi_( Register a, Register s, int sh6) { emit_int32(SRADI_OPCODE | rta(a) | rs(s) | sh162030(sh6) | rc(1)); } +inline void Assembler::srawi( Register a, Register s, int sh5) { emit_int32(SRAWI_OPCODE | rta(a) | rs(s) | sh1620(sh5) | rc(0)); } +inline void Assembler::srawi_( Register a, Register s, int sh5) { emit_int32(SRAWI_OPCODE | rta(a) | rs(s) | sh1620(sh5) | rc(1)); } + +// extended mnemonics for Shift Instructions +inline void Assembler::sldi( Register a, Register s, int sh6) { Assembler::rldicr(a, s, sh6, 63-sh6); } +inline void Assembler::sldi_( Register a, Register s, int sh6) { Assembler::rldicr_(a, s, sh6, 63-sh6); } +inline void Assembler::slwi( Register a, Register s, int sh5) { Assembler::rlwinm(a, s, sh5, 0, 31-sh5); } +inline void Assembler::slwi_( Register a, Register s, int sh5) { Assembler::rlwinm_(a, s, sh5, 0, 31-sh5); } +inline void Assembler::srdi( Register a, Register s, int sh6) { Assembler::rldicl(a, s, 64-sh6, sh6); } +inline void Assembler::srdi_( Register a, Register s, int sh6) { Assembler::rldicl_(a, s, 64-sh6, sh6); } +inline void Assembler::srwi( Register a, Register s, int sh5) { Assembler::rlwinm(a, s, 32-sh5, sh5, 31); } +inline void Assembler::srwi_( Register a, Register s, int sh5) { Assembler::rlwinm_(a, s, 32-sh5, sh5, 31); } + +inline void Assembler::clrrdi( Register a, Register s, int ui6) { Assembler::rldicr(a, s, 0, 63-ui6); } +inline void Assembler::clrrdi_( Register a, Register s, int ui6) { Assembler::rldicr_(a, s, 0, 63-ui6); } +inline void Assembler::clrldi( Register a, Register s, int ui6) { Assembler::rldicl(a, s, 0, ui6); } +inline void Assembler::clrldi_( Register a, Register s, int ui6) { Assembler::rldicl_(a, s, 0, ui6); } +inline void Assembler::clrlsldi( Register a, Register s, int clrl6, int shl6) { Assembler::rldic( a, s, shl6, clrl6-shl6); } +inline void Assembler::clrlsldi_(Register a, Register s, int clrl6, int shl6) { Assembler::rldic_(a, s, shl6, clrl6-shl6); } +inline void Assembler::extrdi( Register a, Register s, int n, int b){ Assembler::rldicl(a, s, b+n, 64-n); } +// testbit with condition register. +inline void Assembler::testbitdi(ConditionRegister cr, Register a, Register s, int ui6) { + Assembler::rldicr(a, s, 63-ui6, 0); + Assembler::cmpdi(cr, a, 0); +} + +// rotate instructions +inline void Assembler::rotldi( Register a, Register s, int n) { Assembler::rldicl(a, s, n, 0); } +inline void Assembler::rotrdi( Register a, Register s, int n) { Assembler::rldicl(a, s, 64-n, 0); } +inline void Assembler::rotlwi( Register a, Register s, int n) { Assembler::rlwinm(a, s, n, 0, 31); } +inline void Assembler::rotrwi( Register a, Register s, int n) { Assembler::rlwinm(a, s, 32-n, 0, 31); } + +inline void Assembler::rldic( Register a, Register s, int sh6, int mb6) { emit_int32(RLDIC_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(0)); } +inline void Assembler::rldic_( Register a, Register s, int sh6, int mb6) { emit_int32(RLDIC_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(1)); } +inline void Assembler::rldicr( Register a, Register s, int sh6, int mb6) { emit_int32(RLDICR_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(0)); } +inline void Assembler::rldicr_( Register a, Register s, int sh6, int mb6) { emit_int32(RLDICR_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(1)); } +inline void Assembler::rldicl( Register a, Register s, int sh6, int me6) { emit_int32(RLDICL_OPCODE | rta(a) | rs(s) | sh162030(sh6) | me2126(me6) | rc(0)); } +inline void Assembler::rldicl_( Register a, Register s, int sh6, int me6) { emit_int32(RLDICL_OPCODE | rta(a) | rs(s) | sh162030(sh6) | me2126(me6) | rc(1)); } +inline void Assembler::rlwinm( Register a, Register s, int sh5, int mb5, int me5){ emit_int32(RLWINM_OPCODE | rta(a) | rs(s) | sh1620(sh5) | mb2125(mb5) | me2630(me5) | rc(0)); } +inline void Assembler::rlwinm_( Register a, Register s, int sh5, int mb5, int me5){ emit_int32(RLWINM_OPCODE | rta(a) | rs(s) | sh1620(sh5) | mb2125(mb5) | me2630(me5) | rc(1)); } +inline void Assembler::rldimi( Register a, Register s, int sh6, int mb6) { emit_int32(RLDIMI_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(0)); } +inline void Assembler::rlwimi( Register a, Register s, int sh5, int mb5, int me5){ emit_int32(RLWIMI_OPCODE | rta(a) | rs(s) | sh1620(sh5) | mb2125(mb5) | me2630(me5) | rc(0)); } +inline void Assembler::rldimi_( Register a, Register s, int sh6, int mb6) { emit_int32(RLDIMI_OPCODE | rta(a) | rs(s) | sh162030(sh6) | mb2126(mb6) | rc(1)); } +inline void Assembler::insrdi( Register a, Register s, int n, int b) { Assembler::rldimi(a, s, 64-(b+n), b); } +inline void Assembler::insrwi( Register a, Register s, int n, int b) { Assembler::rlwimi(a, s, 32-(b+n), b, b+n-1); } + +// PPC 1, section 3.3.2 Fixed-Point Load Instructions +inline void Assembler::lwzx( Register d, Register s1, Register s2) { emit_int32(LWZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::lwz( Register d, int si16, Register s1) { emit_int32(LWZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::lwzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LWZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::lwax( Register d, Register s1, Register s2) { emit_int32(LWAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::lwa( Register d, int si16, Register s1) { emit_int32(LWA_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} + +inline void Assembler::lhzx( Register d, Register s1, Register s2) { emit_int32(LHZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::lhz( Register d, int si16, Register s1) { emit_int32(LHZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::lhzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::lhax( Register d, Register s1, Register s2) { emit_int32(LHAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::lha( Register d, int si16, Register s1) { emit_int32(LHA_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::lhau( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHAU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::lbzx( Register d, Register s1, Register s2) { emit_int32(LBZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::lbz( Register d, int si16, Register s1) { emit_int32(LBZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::lbzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LBZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::ld( Register d, int si16, Register s1) { emit_int32(LD_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} +inline void Assembler::ldx( Register d, Register s1, Register s2) { emit_int32(LDX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::ldu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LDU_OPCODE | rt(d) | ds(si16) | rta0mem(s1));} + +// PPC 1, section 3.3.3 Fixed-Point Store Instructions +inline void Assembler::stwx( Register d, Register s1, Register s2) { emit_int32(STWX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::stw( Register d, int si16, Register s1) { emit_int32(STW_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::stwu( Register d, int si16, Register s1) { emit_int32(STWU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::sthx( Register d, Register s1, Register s2) { emit_int32(STHX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::sth( Register d, int si16, Register s1) { emit_int32(STH_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::sthu( Register d, int si16, Register s1) { emit_int32(STHU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::stbx( Register d, Register s1, Register s2) { emit_int32(STBX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::stb( Register d, int si16, Register s1) { emit_int32(STB_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} +inline void Assembler::stbu( Register d, int si16, Register s1) { emit_int32(STBU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} + +inline void Assembler::std( Register d, int si16, Register s1) { emit_int32(STD_OPCODE | rs(d) | ds(si16) | ra0mem(s1));} +inline void Assembler::stdx( Register d, Register s1, Register s2) { emit_int32(STDX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} +inline void Assembler::stdu( Register d, int si16, Register s1) { emit_int32(STDU_OPCODE | rs(d) | ds(si16) | rta0mem(s1));} +inline void Assembler::stdux(Register s, Register a, Register b) { emit_int32(STDUX_OPCODE| rs(s) | rta0mem(a) | rb(b));} + +// PPC 1, section 3.3.13 Move To/From System Register Instructions +inline void Assembler::mtlr( Register s1) { emit_int32(MTLR_OPCODE | rs(s1)); } +inline void Assembler::mflr( Register d ) { emit_int32(MFLR_OPCODE | rt(d)); } +inline void Assembler::mtctr(Register s1) { emit_int32(MTCTR_OPCODE | rs(s1)); } +inline void Assembler::mfctr(Register d ) { emit_int32(MFCTR_OPCODE | rt(d)); } +inline void Assembler::mtcrf(int afxm, Register s){ emit_int32(MTCRF_OPCODE | fxm(afxm) | rs(s)); } +inline void Assembler::mfcr( Register d ) { emit_int32(MFCR_OPCODE | rt(d)); } +inline void Assembler::mcrf( ConditionRegister crd, ConditionRegister cra) + { emit_int32(MCRF_OPCODE | bf(crd) | bfa(cra)); } +inline void Assembler::mtcr( Register s) { Assembler::mtcrf(0xff, s); } + +// SAP JVM 2006-02-13 PPC branch instruction. +// PPC 1, section 2.4.1 Branch Instructions +inline void Assembler::b( address a, relocInfo::relocType rt) { emit_data(BXX_OPCODE| li(disp( intptr_t(a), intptr_t(pc()))) |aa(0)|lk(0), rt); } +inline void Assembler::b( Label& L) { b( target(L)); } +inline void Assembler::bl(address a, relocInfo::relocType rt) { emit_data(BXX_OPCODE| li(disp( intptr_t(a), intptr_t(pc()))) |aa(0)|lk(1), rt); } +inline void Assembler::bl(Label& L) { bl(target(L)); } +inline void Assembler::bc( int boint, int biint, address a, relocInfo::relocType rt) { emit_data(BCXX_OPCODE| bo(boint) | bi(biint) | bd(disp( intptr_t(a), intptr_t(pc()))) | aa(0) | lk(0), rt); } +inline void Assembler::bc( int boint, int biint, Label& L) { bc(boint, biint, target(L)); } +inline void Assembler::bcl(int boint, int biint, address a, relocInfo::relocType rt) { emit_data(BCXX_OPCODE| bo(boint) | bi(biint) | bd(disp( intptr_t(a), intptr_t(pc()))) | aa(0)|lk(1)); } +inline void Assembler::bcl(int boint, int biint, Label& L) { bcl(boint, biint, target(L)); } + +inline void Assembler::bclr( int boint, int biint, int bhint, relocInfo::relocType rt) { emit_data(BCLR_OPCODE | bo(boint) | bi(biint) | bh(bhint) | aa(0) | lk(0), rt); } +inline void Assembler::bclrl( int boint, int biint, int bhint, relocInfo::relocType rt) { emit_data(BCLR_OPCODE | bo(boint) | bi(biint) | bh(bhint) | aa(0) | lk(1), rt); } +inline void Assembler::bcctr( int boint, int biint, int bhint, relocInfo::relocType rt) { emit_data(BCCTR_OPCODE| bo(boint) | bi(biint) | bh(bhint) | aa(0) | lk(0), rt); } +inline void Assembler::bcctrl(int boint, int biint, int bhint, relocInfo::relocType rt) { emit_data(BCCTR_OPCODE| bo(boint) | bi(biint) | bh(bhint) | aa(0) | lk(1), rt); } + +// helper function for b +inline bool Assembler::is_within_range_of_b(address a, address pc) { + // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file). + if ((((uint64_t)a) & 0x3) != 0) return false; + + const int range = 1 << (29-6); // li field is from bit 6 to bit 29. + int value = disp(intptr_t(a), intptr_t(pc)); + bool result = -range <= value && value < range-1; +#ifdef ASSERT + if (result) li(value); // Assert that value is in correct range. +#endif + return result; +} + +// helper functions for bcxx. +inline bool Assembler::is_within_range_of_bcxx(address a, address pc) { + // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file). + if ((((uint64_t)a) & 0x3) != 0) return false; + + const int range = 1 << (29-16); // bd field is from bit 16 to bit 29. + int value = disp(intptr_t(a), intptr_t(pc)); + bool result = -range <= value && value < range-1; +#ifdef ASSERT + if (result) bd(value); // Assert that value is in correct range. +#endif + return result; +} + +// Get the destination of a bxx branch (b, bl, ba, bla). +address Assembler::bxx_destination(address baddr) { return bxx_destination(*(int*)baddr, baddr); } +address Assembler::bxx_destination(int instr, address pc) { return (address)bxx_destination_offset(instr, (intptr_t)pc); } +intptr_t Assembler::bxx_destination_offset(int instr, intptr_t bxx_pos) { + intptr_t displ = inv_li_field(instr); + return bxx_pos + displ; +} + +// Extended mnemonics for Branch Instructions +inline void Assembler::blt(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs1, bi0(crx, less), L); } +inline void Assembler::bgt(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs1, bi0(crx, greater), L); } +inline void Assembler::beq(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs1, bi0(crx, equal), L); } +inline void Assembler::bso(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs1, bi0(crx, summary_overflow), L); } +inline void Assembler::bge(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs0, bi0(crx, less), L); } +inline void Assembler::ble(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs0, bi0(crx, greater), L); } +inline void Assembler::bne(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs0, bi0(crx, equal), L); } +inline void Assembler::bns(ConditionRegister crx, Label& L) { Assembler::bc(bcondCRbiIs0, bi0(crx, summary_overflow), L); } + +// Branch instructions with static prediction hints. +inline void Assembler::blt_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsTaken, bi0(crx, less), L); } +inline void Assembler::bgt_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsTaken, bi0(crx, greater), L); } +inline void Assembler::beq_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsTaken, bi0(crx, equal), L); } +inline void Assembler::bso_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsTaken, bi0(crx, summary_overflow), L); } +inline void Assembler::bge_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsTaken, bi0(crx, less), L); } +inline void Assembler::ble_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsTaken, bi0(crx, greater), L); } +inline void Assembler::bne_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsTaken, bi0(crx, equal), L); } +inline void Assembler::bns_predict_taken (ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsTaken, bi0(crx, summary_overflow), L); } +inline void Assembler::blt_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsNotTaken, bi0(crx, less), L); } +inline void Assembler::bgt_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsNotTaken, bi0(crx, greater), L); } +inline void Assembler::beq_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsNotTaken, bi0(crx, equal), L); } +inline void Assembler::bso_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs1_bhintIsNotTaken, bi0(crx, summary_overflow), L); } +inline void Assembler::bge_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsNotTaken, bi0(crx, less), L); } +inline void Assembler::ble_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsNotTaken, bi0(crx, greater), L); } +inline void Assembler::bne_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsNotTaken, bi0(crx, equal), L); } +inline void Assembler::bns_predict_not_taken(ConditionRegister crx, Label& L) { bc(bcondCRbiIs0_bhintIsNotTaken, bi0(crx, summary_overflow), L); } + +// For use in conjunction with testbitdi: +inline void Assembler::btrue( ConditionRegister crx, Label& L) { Assembler::bne(crx, L); } +inline void Assembler::bfalse(ConditionRegister crx, Label& L) { Assembler::beq(crx, L); } + +inline void Assembler::bltl(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs1, bi0(crx, less), L); } +inline void Assembler::bgtl(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs1, bi0(crx, greater), L); } +inline void Assembler::beql(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs1, bi0(crx, equal), L); } +inline void Assembler::bsol(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs1, bi0(crx, summary_overflow), L); } +inline void Assembler::bgel(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs0, bi0(crx, less), L); } +inline void Assembler::blel(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs0, bi0(crx, greater), L); } +inline void Assembler::bnel(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs0, bi0(crx, equal), L); } +inline void Assembler::bnsl(ConditionRegister crx, Label& L) { Assembler::bcl(bcondCRbiIs0, bi0(crx, summary_overflow), L); } + +// Extended mnemonics for Branch Instructions via LR. +// We use `blr' for returns. +inline void Assembler::blr(relocInfo::relocType rt) { Assembler::bclr(bcondAlways, 0, bhintbhBCLRisReturn, rt); } + +// Extended mnemonics for Branch Instructions with CTR. +// Bdnz means `decrement CTR and jump to L if CTR is not zero'. +inline void Assembler::bdnz(Label& L) { Assembler::bc(16, 0, L); } +// Decrement and branch if result is zero. +inline void Assembler::bdz(Label& L) { Assembler::bc(18, 0, L); } +// We use `bctr[l]' for jumps/calls in function descriptor glue +// code, e.g. for calls to runtime functions. +inline void Assembler::bctr( relocInfo::relocType rt) { Assembler::bcctr(bcondAlways, 0, bhintbhBCCTRisNotReturnButSame, rt); } +inline void Assembler::bctrl(relocInfo::relocType rt) { Assembler::bcctrl(bcondAlways, 0, bhintbhBCCTRisNotReturnButSame, rt); } +// Conditional jumps/branches via CTR. +inline void Assembler::beqctr( ConditionRegister crx, relocInfo::relocType rt) { Assembler::bcctr( bcondCRbiIs1, bi0(crx, equal), bhintbhBCCTRisNotReturnButSame, rt); } +inline void Assembler::beqctrl(ConditionRegister crx, relocInfo::relocType rt) { Assembler::bcctrl(bcondCRbiIs1, bi0(crx, equal), bhintbhBCCTRisNotReturnButSame, rt); } +inline void Assembler::bnectr( ConditionRegister crx, relocInfo::relocType rt) { Assembler::bcctr( bcondCRbiIs0, bi0(crx, equal), bhintbhBCCTRisNotReturnButSame, rt); } +inline void Assembler::bnectrl(ConditionRegister crx, relocInfo::relocType rt) { Assembler::bcctrl(bcondCRbiIs0, bi0(crx, equal), bhintbhBCCTRisNotReturnButSame, rt); } + +// condition register logic instructions +inline void Assembler::crand( int d, int s1, int s2) { emit_int32(CRAND_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::crnand(int d, int s1, int s2) { emit_int32(CRNAND_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::cror( int d, int s1, int s2) { emit_int32(CROR_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::crxor( int d, int s1, int s2) { emit_int32(CRXOR_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::crnor( int d, int s1, int s2) { emit_int32(CRNOR_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::creqv( int d, int s1, int s2) { emit_int32(CREQV_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); } +inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE | bt(d) | ba(s1) | bb(s2)); } + +// PPC 2, section 3.2.1 Instruction Cache Instructions +inline void Assembler::icbi( Register s1, Register s2) { emit_int32( ICBI_OPCODE | ra0mem(s1) | rb(s2) ); } +// PPC 2, section 3.2.2 Data Cache Instructions +//inline void Assembler::dcba( Register s1, Register s2) { emit_int32( DCBA_OPCODE | ra0mem(s1) | rb(s2) ); } +inline void Assembler::dcbz( Register s1, Register s2) { emit_int32( DCBZ_OPCODE | ra0mem(s1) | rb(s2) ); } +inline void Assembler::dcbst( Register s1, Register s2) { emit_int32( DCBST_OPCODE | ra0mem(s1) | rb(s2) ); } +inline void Assembler::dcbf( Register s1, Register s2) { emit_int32( DCBF_OPCODE | ra0mem(s1) | rb(s2) ); } +// dcache read hint +inline void Assembler::dcbt( Register s1, Register s2) { emit_int32( DCBT_OPCODE | ra0mem(s1) | rb(s2) ); } +inline void Assembler::dcbtct( Register s1, Register s2, int ct) { emit_int32( DCBT_OPCODE | ra0mem(s1) | rb(s2) | thct(ct)); } +inline void Assembler::dcbtds( Register s1, Register s2, int ds) { emit_int32( DCBT_OPCODE | ra0mem(s1) | rb(s2) | thds(ds)); } +// dcache write hint +inline void Assembler::dcbtst( Register s1, Register s2) { emit_int32( DCBTST_OPCODE | ra0mem(s1) | rb(s2) ); } +inline void Assembler::dcbtstct(Register s1, Register s2, int ct) { emit_int32( DCBTST_OPCODE | ra0mem(s1) | rb(s2) | thct(ct)); } + +// machine barrier instructions: +inline void Assembler::sync(int a) { emit_int32( SYNC_OPCODE | l910(a)); } +inline void Assembler::sync() { Assembler::sync(0); } +inline void Assembler::lwsync() { Assembler::sync(1); } +inline void Assembler::ptesync() { Assembler::sync(2); } +inline void Assembler::eieio() { emit_int32( EIEIO_OPCODE); } +inline void Assembler::isync() { emit_int32( ISYNC_OPCODE); } + +inline void Assembler::release() { Assembler::lwsync(); } +inline void Assembler::acquire() { Assembler::lwsync(); } +inline void Assembler::fence() { Assembler::sync(); } + +// atomics +// Use ra0mem to disallow R0 as base. +inline void Assembler::lwarx_unchecked(Register d, Register a, Register b, int eh1) { emit_int32( LWARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); } +inline void Assembler::ldarx_unchecked(Register d, Register a, Register b, int eh1) { emit_int32( LDARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); } +inline bool Assembler::lxarx_hint_exclusive_access() { return VM_Version::has_lxarxeh(); } +inline void Assembler::lwarx( Register d, Register a, Register b, bool hint_exclusive_access) { lwarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); } +inline void Assembler::ldarx( Register d, Register a, Register b, bool hint_exclusive_access) { ldarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); } +inline void Assembler::stwcx_(Register s, Register a, Register b) { emit_int32( STWCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); } +inline void Assembler::stdcx_(Register s, Register a, Register b) { emit_int32( STDCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); } + +// Instructions for adjusting thread priority +// for simultaneous multithreading (SMT) on POWER5. +inline void Assembler::smt_prio_very_low() { Assembler::or_unchecked(R31, R31, R31); } +inline void Assembler::smt_prio_low() { Assembler::or_unchecked(R1, R1, R1); } +inline void Assembler::smt_prio_medium_low() { Assembler::or_unchecked(R6, R6, R6); } +inline void Assembler::smt_prio_medium() { Assembler::or_unchecked(R2, R2, R2); } +inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5, R5, R5); } +inline void Assembler::smt_prio_high() { Assembler::or_unchecked(R3, R3, R3); } + +inline void Assembler::twi_0(Register a) { twi_unchecked(0, a, 0);} + +// trap instructions +inline void Assembler::tdi_unchecked(int tobits, Register a, int si16){ emit_int32( TDI_OPCODE | to(tobits) | ra(a) | si(si16)); } +inline void Assembler::twi_unchecked(int tobits, Register a, int si16){ emit_int32( TWI_OPCODE | to(tobits) | ra(a) | si(si16)); } +inline void Assembler::tdi(int tobits, Register a, int si16) { assert(UseSIGTRAP, "precondition"); tdi_unchecked(tobits, a, si16); } +inline void Assembler::twi(int tobits, Register a, int si16) { assert(UseSIGTRAP, "precondition"); twi_unchecked(tobits, a, si16); } +inline void Assembler::td( int tobits, Register a, Register b) { assert(UseSIGTRAP, "precondition"); emit_int32( TD_OPCODE | to(tobits) | ra(a) | rb(b)); } +inline void Assembler::tw( int tobits, Register a, Register b) { assert(UseSIGTRAP, "precondition"); emit_int32( TW_OPCODE | to(tobits) | ra(a) | rb(b)); } + +// FLOATING POINT instructions ppc. +// PPC 1, section 4.6.2 Floating-Point Load Instructions +// Use ra0mem instead of ra in some instructions below. +inline void Assembler::lfs( FloatRegister d, int si16, Register a) { emit_int32( LFS_OPCODE | frt(d) | ra0mem(a) | simm(si16,16)); } +inline void Assembler::lfsu(FloatRegister d, int si16, Register a) { emit_int32( LFSU_OPCODE | frt(d) | ra(a) | simm(si16,16)); } +inline void Assembler::lfsx(FloatRegister d, Register a, Register b) { emit_int32( LFSX_OPCODE | frt(d) | ra0mem(a) | rb(b)); } +inline void Assembler::lfd( FloatRegister d, int si16, Register a) { emit_int32( LFD_OPCODE | frt(d) | ra0mem(a) | simm(si16,16)); } +inline void Assembler::lfdu(FloatRegister d, int si16, Register a) { emit_int32( LFDU_OPCODE | frt(d) | ra(a) | simm(si16,16)); } +inline void Assembler::lfdx(FloatRegister d, Register a, Register b) { emit_int32( LFDX_OPCODE | frt(d) | ra0mem(a) | rb(b)); } + +// PPC 1, section 4.6.3 Floating-Point Store Instructions +// Use ra0mem instead of ra in some instructions below. +inline void Assembler::stfs( FloatRegister s, int si16, Register a) { emit_int32( STFS_OPCODE | frs(s) | ra0mem(a) | simm(si16,16)); } +inline void Assembler::stfsu(FloatRegister s, int si16, Register a) { emit_int32( STFSU_OPCODE | frs(s) | ra(a) | simm(si16,16)); } +inline void Assembler::stfsx(FloatRegister s, Register a, Register b){ emit_int32( STFSX_OPCODE | frs(s) | ra0mem(a) | rb(b)); } +inline void Assembler::stfd( FloatRegister s, int si16, Register a) { emit_int32( STFD_OPCODE | frs(s) | ra0mem(a) | simm(si16,16)); } +inline void Assembler::stfdu(FloatRegister s, int si16, Register a) { emit_int32( STFDU_OPCODE | frs(s) | ra(a) | simm(si16,16)); } +inline void Assembler::stfdx(FloatRegister s, Register a, Register b){ emit_int32( STFDX_OPCODE | frs(s) | ra0mem(a) | rb(b)); } + +// PPC 1, section 4.6.4 Floating-Point Move Instructions +inline void Assembler::fmr( FloatRegister d, FloatRegister b) { emit_int32( FMR_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fmr_(FloatRegister d, FloatRegister b) { emit_int32( FMR_OPCODE | frt(d) | frb(b) | rc(1)); } + +// These are special Power6 opcodes, reused for "lfdepx" and "stfdepx" +// on Power7. Do not use. +//inline void Assembler::mffgpr( FloatRegister d, Register b) { emit_int32( MFFGPR_OPCODE | frt(d) | rb(b) | rc(0)); } +//inline void Assembler::mftgpr( Register d, FloatRegister b) { emit_int32( MFTGPR_OPCODE | rt(d) | frb(b) | rc(0)); } +// add cmpb and popcntb to detect ppc power version. +inline void Assembler::cmpb( Register a, Register s, Register b) { emit_int32( CMPB_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::popcntb(Register a, Register s) { emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); }; +inline void Assembler::popcntw(Register a, Register s) { emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); }; +inline void Assembler::popcntd(Register a, Register s) { emit_int32( POPCNTD_OPCODE | rta(a) | rs(s)); }; + +inline void Assembler::fneg( FloatRegister d, FloatRegister b) { emit_int32( FNEG_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fneg_( FloatRegister d, FloatRegister b) { emit_int32( FNEG_OPCODE | frt(d) | frb(b) | rc(1)); } +inline void Assembler::fabs( FloatRegister d, FloatRegister b) { emit_int32( FABS_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fabs_( FloatRegister d, FloatRegister b) { emit_int32( FABS_OPCODE | frt(d) | frb(b) | rc(1)); } +inline void Assembler::fnabs( FloatRegister d, FloatRegister b) { emit_int32( FNABS_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fnabs_(FloatRegister d, FloatRegister b) { emit_int32( FNABS_OPCODE | frt(d) | frb(b) | rc(1)); } + +// PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic Instructions +inline void Assembler::fadd( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FADD_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fadd_( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FADD_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } +inline void Assembler::fadds( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FADDS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fadds_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FADDS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } +inline void Assembler::fsub( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FSUB_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fsub_( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FSUB_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } +inline void Assembler::fsubs( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FSUBS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fsubs_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FSUBS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } +inline void Assembler::fmul( FloatRegister d, FloatRegister a, FloatRegister c) { emit_int32( FMUL_OPCODE | frt(d) | fra(a) | frc(c) | rc(0)); } +inline void Assembler::fmul_( FloatRegister d, FloatRegister a, FloatRegister c) { emit_int32( FMUL_OPCODE | frt(d) | fra(a) | frc(c) | rc(1)); } +inline void Assembler::fmuls( FloatRegister d, FloatRegister a, FloatRegister c) { emit_int32( FMULS_OPCODE | frt(d) | fra(a) | frc(c) | rc(0)); } +inline void Assembler::fmuls_(FloatRegister d, FloatRegister a, FloatRegister c) { emit_int32( FMULS_OPCODE | frt(d) | fra(a) | frc(c) | rc(1)); } +inline void Assembler::fdiv( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIV_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fdiv_( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIV_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } +inline void Assembler::fdivs( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); } +inline void Assembler::fdivs_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); } + +// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions +inline void Assembler::frsp( FloatRegister d, FloatRegister b) { emit_int32( FRSP_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fctid( FloatRegister d, FloatRegister b) { emit_int32( FCTID_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fctidz(FloatRegister d, FloatRegister b) { emit_int32( FCTIDZ_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fctiw( FloatRegister d, FloatRegister b) { emit_int32( FCTIW_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fctiwz(FloatRegister d, FloatRegister b) { emit_int32( FCTIWZ_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fcfid( FloatRegister d, FloatRegister b) { emit_int32( FCFID_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); } + +// PPC 1, section 4.6.7 Floating-Point Compare Instructions +inline void Assembler::fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b) { emit_int32( FCMPU_OPCODE | bf(crx) | fra(a) | frb(b)); } + +// PPC 1, section 5.2.1 Floating-Point Arithmetic Instructions +inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { emit_int32( FSQRT_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); } + +// Vector instructions for >= Power6. +inline void Assembler::lvebx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEBX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvehx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEHX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvewx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEWX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvx( VectorRegister d, Register s1, Register s2) { emit_int32( LVX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvxl( VectorRegister d, Register s1, Register s2) { emit_int32( LVXL_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stvebx(VectorRegister d, Register s1, Register s2) { emit_int32( STVEBX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stvehx(VectorRegister d, Register s1, Register s2) { emit_int32( STVEHX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stvewx(VectorRegister d, Register s1, Register s2) { emit_int32( STVEWX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stvx( VectorRegister d, Register s1, Register s2) { emit_int32( STVX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stvxl( VectorRegister d, Register s1, Register s2) { emit_int32( STVXL_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvsl( VectorRegister d, Register s1, Register s2) { emit_int32( LVSL_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::lvsr( VectorRegister d, Register s1, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } + +inline void Assembler::vpkpx( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKPX_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkshss( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSHSS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkswss( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSWSS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkshus( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSHUS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkswus( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSWUS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkuhum( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKUHUM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkuwum( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKUWUM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkuhus( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKUHUS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpkuwus( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKUWUS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vupkhpx( VectorRegister d, VectorRegister b) { emit_int32( VUPKHPX_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vupkhsb( VectorRegister d, VectorRegister b) { emit_int32( VUPKHSB_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vupkhsh( VectorRegister d, VectorRegister b) { emit_int32( VUPKHSH_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vupklpx( VectorRegister d, VectorRegister b) { emit_int32( VUPKLPX_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vupklsb( VectorRegister d, VectorRegister b) { emit_int32( VUPKLSB_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vupklsh( VectorRegister d, VectorRegister b) { emit_int32( VUPKLSH_OPCODE | vrt(d) | vrb(b)); } +inline void Assembler::vmrghb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGHB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmrghw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGHW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmrghh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGHH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmrglb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGLB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmrglw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGLW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmrglh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMRGLH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsplt( VectorRegister d, int ui4, VectorRegister b) { emit_int32( VSPLT_OPCODE | vrt(d) | vsplt_uim(uimm(ui4,4)) | vrb(b)); } +inline void Assembler::vsplth( VectorRegister d, int ui3, VectorRegister b) { emit_int32( VSPLTH_OPCODE | vrt(d) | vsplt_uim(uimm(ui3,3)) | vrb(b)); } +inline void Assembler::vspltw( VectorRegister d, int ui2, VectorRegister b) { emit_int32( VSPLTW_OPCODE | vrt(d) | vsplt_uim(uimm(ui2,2)) | vrb(b)); } +inline void Assembler::vspltisb(VectorRegister d, int si5) { emit_int32( VSPLTISB_OPCODE| vrt(d) | vsplti_sim(simm(si5,5))); } +inline void Assembler::vspltish(VectorRegister d, int si5) { emit_int32( VSPLTISH_OPCODE| vrt(d) | vsplti_sim(simm(si5,5))); } +inline void Assembler::vspltisw(VectorRegister d, int si5) { emit_int32( VSPLTISW_OPCODE| vrt(d) | vsplti_sim(simm(si5,5))); } +inline void Assembler::vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VPERM_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); } +inline void Assembler::vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VSEL_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); } +inline void Assembler::vsl( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSL_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4) { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(simm(si4,4))); } +inline void Assembler::vslo( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLO_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsr( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSR_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsro( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRO_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddcuw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDCUW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddshs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDSHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddsbs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDSBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddsws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDSWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddubm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vadduwm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vadduhm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddubs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vadduws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vadduhs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubcuw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBCUW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubshs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBSHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubsbs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBSBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubsws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBSWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsububm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUBM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubuwm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUWM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubuhm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUHM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsububs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubuws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsubuhs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUBUHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmulesb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULESB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmuleub( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULEUB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmulesh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULESH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmuleuh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULEUH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmulosb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULOSB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmuloub( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULOUB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmulosh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULOSH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmulouh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMULOUH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmhaddshs(VectorRegister d,VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMHADDSHS_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmhraddshs(VectorRegister d,VectorRegister a,VectorRegister b, VectorRegister c) { emit_int32( VMHRADDSHS_OPCODE| vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmladduhm(VectorRegister d,VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMLADDUHM_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsubuhm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUBUHM_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsummbm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUMMBM_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsumshm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUMSHM_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsumshs(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUMSHS_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsumuhm(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUMUHM_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vmsumuhs(VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VMSUMUHS_OPCODE | vrt(d) | vra(a) | vrb(b)| vrc(c)); } +inline void Assembler::vsumsws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUMSWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsum2sws(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUM2SWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsum4sbs(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUM4SBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsum4ubs(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUM4UBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsum4shs(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSUM4SHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavgsb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGSB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavgsw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGSW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavgsh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGSH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavgub( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGUB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavguw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGUW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vavguh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAVGUH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxsb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXSB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxsw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXSW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxsh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXSH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxub( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXUB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxuw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXUW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmaxuh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMAXUH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminsb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINSB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminsw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINSW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminsh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINSH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminub( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINUB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminuw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINUW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vminuh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VMINUH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vcmpequb(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpequh(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpequw(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtsh(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtsb(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtsw(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtub(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtuh(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpgtuw(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(0)); } +inline void Assembler::vcmpequb_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpequh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpequw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPEQUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtsh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtsb_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtsw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTSW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtub_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtuh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vcmpgtuw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } +inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAND_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vandc( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vnor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vxor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VXOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vrlb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vrlw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vrlh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vslb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vskw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSKW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vslh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsrb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsrw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsrh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsrab( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRAB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsraw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRAW_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsrah( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRAH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::mtvscr( VectorRegister b) { emit_int32( MTVSCR_OPCODE | vrb(b)); } +inline void Assembler::mfvscr( VectorRegister d) { emit_int32( MFVSCR_OPCODE | vrt(d)); } + +// ra0 version +inline void Assembler::lwzx( Register d, Register s2) { emit_int32( LWZX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::lwz( Register d, int si16 ) { emit_int32( LWZ_OPCODE | rt(d) | d1(si16));} +inline void Assembler::lwax( Register d, Register s2) { emit_int32( LWAX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::lwa( Register d, int si16 ) { emit_int32( LWA_OPCODE | rt(d) | ds(si16));} +inline void Assembler::lhzx( Register d, Register s2) { emit_int32( LHZX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::lhz( Register d, int si16 ) { emit_int32( LHZ_OPCODE | rt(d) | d1(si16));} +inline void Assembler::lhax( Register d, Register s2) { emit_int32( LHAX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::lha( Register d, int si16 ) { emit_int32( LHA_OPCODE | rt(d) | d1(si16));} +inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));} +inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));} +inline void Assembler::ldx( Register d, Register s2) { emit_int32( LDX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::stwx( Register d, Register s2) { emit_int32( STWX_OPCODE | rs(d) | rb(s2));} +inline void Assembler::stw( Register d, int si16 ) { emit_int32( STW_OPCODE | rs(d) | d1(si16));} +inline void Assembler::sthx( Register d, Register s2) { emit_int32( STHX_OPCODE | rs(d) | rb(s2));} +inline void Assembler::sth( Register d, int si16 ) { emit_int32( STH_OPCODE | rs(d) | d1(si16));} +inline void Assembler::stbx( Register d, Register s2) { emit_int32( STBX_OPCODE | rs(d) | rb(s2));} +inline void Assembler::stb( Register d, int si16 ) { emit_int32( STB_OPCODE | rs(d) | d1(si16));} +inline void Assembler::std( Register d, int si16 ) { emit_int32( STD_OPCODE | rs(d) | ds(si16));} +inline void Assembler::stdx( Register d, Register s2) { emit_int32( STDX_OPCODE | rs(d) | rb(s2));} + +// ra0 version +inline void Assembler::icbi( Register s2) { emit_int32( ICBI_OPCODE | rb(s2) ); } +//inline void Assembler::dcba( Register s2) { emit_int32( DCBA_OPCODE | rb(s2) ); } +inline void Assembler::dcbz( Register s2) { emit_int32( DCBZ_OPCODE | rb(s2) ); } +inline void Assembler::dcbst( Register s2) { emit_int32( DCBST_OPCODE | rb(s2) ); } +inline void Assembler::dcbf( Register s2) { emit_int32( DCBF_OPCODE | rb(s2) ); } +inline void Assembler::dcbt( Register s2) { emit_int32( DCBT_OPCODE | rb(s2) ); } +inline void Assembler::dcbtct( Register s2, int ct) { emit_int32( DCBT_OPCODE | rb(s2) | thct(ct)); } +inline void Assembler::dcbtds( Register s2, int ds) { emit_int32( DCBT_OPCODE | rb(s2) | thds(ds)); } +inline void Assembler::dcbtst( Register s2) { emit_int32( DCBTST_OPCODE | rb(s2) ); } +inline void Assembler::dcbtstct(Register s2, int ct) { emit_int32( DCBTST_OPCODE | rb(s2) | thct(ct)); } + +// ra0 version +inline void Assembler::lwarx_unchecked(Register d, Register b, int eh1) { emit_int32( LWARX_OPCODE | rt(d) | rb(b) | eh(eh1)); } +inline void Assembler::ldarx_unchecked(Register d, Register b, int eh1) { emit_int32( LDARX_OPCODE | rt(d) | rb(b) | eh(eh1)); } +inline void Assembler::lwarx( Register d, Register b, bool hint_exclusive_access){ lwarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); } +inline void Assembler::ldarx( Register d, Register b, bool hint_exclusive_access){ ldarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); } +inline void Assembler::stwcx_(Register s, Register b) { emit_int32( STWCX_OPCODE | rs(s) | rb(b) | rc(1)); } +inline void Assembler::stdcx_(Register s, Register b) { emit_int32( STDCX_OPCODE | rs(s) | rb(b) | rc(1)); } + +// ra0 version +inline void Assembler::lfs( FloatRegister d, int si16) { emit_int32( LFS_OPCODE | frt(d) | simm(si16,16)); } +inline void Assembler::lfsx(FloatRegister d, Register b) { emit_int32( LFSX_OPCODE | frt(d) | rb(b)); } +inline void Assembler::lfd( FloatRegister d, int si16) { emit_int32( LFD_OPCODE | frt(d) | simm(si16,16)); } +inline void Assembler::lfdx(FloatRegister d, Register b) { emit_int32( LFDX_OPCODE | frt(d) | rb(b)); } + +// ra0 version +inline void Assembler::stfs( FloatRegister s, int si16) { emit_int32( STFS_OPCODE | frs(s) | simm(si16, 16)); } +inline void Assembler::stfsx(FloatRegister s, Register b) { emit_int32( STFSX_OPCODE | frs(s) | rb(b)); } +inline void Assembler::stfd( FloatRegister s, int si16) { emit_int32( STFD_OPCODE | frs(s) | simm(si16, 16)); } +inline void Assembler::stfdx(FloatRegister s, Register b) { emit_int32( STFDX_OPCODE | frs(s) | rb(b)); } + +// ra0 version +inline void Assembler::lvebx( VectorRegister d, Register s2) { emit_int32( LVEBX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvehx( VectorRegister d, Register s2) { emit_int32( LVEHX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvewx( VectorRegister d, Register s2) { emit_int32( LVEWX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvx( VectorRegister d, Register s2) { emit_int32( LVX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvxl( VectorRegister d, Register s2) { emit_int32( LVXL_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::stvebx(VectorRegister d, Register s2) { emit_int32( STVEBX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::stvehx(VectorRegister d, Register s2) { emit_int32( STVEHX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::stvewx(VectorRegister d, Register s2) { emit_int32( STVEWX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::stvx( VectorRegister d, Register s2) { emit_int32( STVX_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::stvxl( VectorRegister d, Register s2) { emit_int32( STVXL_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvsl( VectorRegister d, Register s2) { emit_int32( LVSL_OPCODE | vrt(d) | rb(s2)); } +inline void Assembler::lvsr( VectorRegister d, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | rb(s2)); } + + +inline void Assembler::load_const(Register d, void* x, Register tmp) { + load_const(d, (long)x, tmp); +} + +// Load a 64 bit constant encoded by a `Label'. This works for bound +// labels as well as unbound ones. For unbound labels, the code will +// be patched as soon as the label gets bound. +inline void Assembler::load_const(Register d, Label& L, Register tmp) { + load_const(d, target(L), tmp); +} + +// Load a 64 bit constant encoded by an AddressLiteral. patchable. +inline void Assembler::load_const(Register d, AddressLiteral& a, Register tmp) { + assert(d != R0, "R0 not allowed"); + // First relocate (we don't change the offset in the RelocationHolder, + // just pass a.rspec()), then delegate to load_const(Register, long). + relocate(a.rspec()); + load_const(d, (long)a.value(), tmp); +} + + +#endif // CPU_PPC_VM_ASSEMBLER_PPC_INLINE_HPP diff --git a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp new file mode 100644 index 00000000000..3706c984b37 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_BYTECODEINTERPRETER_PPC_HPP +#define CPU_PPC_VM_BYTECODEINTERPRETER_PPC_HPP + +// Platform specific for C++ based Interpreter +#define LOTS_OF_REGS /* Lets interpreter use plenty of registers */ + +private: + + // Save the bottom of the stack after frame manager setup. For ease of restoration after return + // from recursive interpreter call. + intptr_t* _frame_bottom; // Saved bottom of frame manager frame. + address _last_Java_pc; // Pc to return to in frame manager. + intptr_t* _last_Java_fp; // frame pointer + intptr_t* _last_Java_sp; // stack pointer + interpreterState _self_link; // Previous interpreter state // sometimes points to self??? + double _native_fresult; // Save result of native calls that might return floats. + intptr_t _native_lresult; // Save result of native calls that might return handle/longs. + +public: + address last_Java_pc(void) { return _last_Java_pc; } + intptr_t* last_Java_fp(void) { return _last_Java_fp; } + + static ByteSize native_lresult_offset() { + return byte_offset_of(BytecodeInterpreter, _native_lresult); + } + + static ByteSize native_fresult_offset() { + return byte_offset_of(BytecodeInterpreter, _native_fresult); + } + + static void pd_layout_interpreterState(interpreterState istate, address last_Java_pc, intptr_t* last_Java_fp); + +#define SET_LAST_JAVA_FRAME() THREAD->frame_anchor()->set(istate->_last_Java_sp, istate->_last_Java_pc); +#define RESET_LAST_JAVA_FRAME() THREAD->frame_anchor()->clear(); + + +// Macros for accessing the stack. +#undef STACK_INT +#undef STACK_FLOAT +#undef STACK_ADDR +#undef STACK_OBJECT +#undef STACK_DOUBLE +#undef STACK_LONG + +// JavaStack Implementation +#define STACK_SLOT(offset) ((address) &topOfStack[-(offset)]) +#define STACK_INT(offset) (*((jint*) &topOfStack[-(offset)])) +#define STACK_FLOAT(offset) (*((jfloat *) &topOfStack[-(offset)])) +#define STACK_OBJECT(offset) (*((oop *) &topOfStack [-(offset)])) +#define STACK_DOUBLE(offset) (((VMJavaVal64*) &topOfStack[-(offset)])->d) +#define STACK_LONG(offset) (((VMJavaVal64 *) &topOfStack[-(offset)])->l) + +#define SET_STACK_SLOT(value, offset) (*(intptr_t*)&topOfStack[-(offset)] = *(intptr_t*)(value)) +#define SET_STACK_ADDR(value, offset) (*((address *)&topOfStack[-(offset)]) = (value)) +#define SET_STACK_INT(value, offset) (*((jint *)&topOfStack[-(offset)]) = (value)) +#define SET_STACK_FLOAT(value, offset) (*((jfloat *)&topOfStack[-(offset)]) = (value)) +#define SET_STACK_OBJECT(value, offset) (*((oop *)&topOfStack[-(offset)]) = (value)) +#define SET_STACK_DOUBLE(value, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->d = (value)) +#define SET_STACK_DOUBLE_FROM_ADDR(addr, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->d = \ + ((VMJavaVal64*)(addr))->d) +#define SET_STACK_LONG(value, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->l = (value)) +#define SET_STACK_LONG_FROM_ADDR(addr, offset) (((VMJavaVal64*)&topOfStack[-(offset)])->l = \ + ((VMJavaVal64*)(addr))->l) +// JavaLocals implementation + +#define LOCALS_SLOT(offset) ((intptr_t*)&locals[-(offset)]) +#define LOCALS_ADDR(offset) ((address)locals[-(offset)]) +#define LOCALS_INT(offset) (*(jint*)&(locals[-(offset)])) +#define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) +#define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)])) +#define LOCALS_DOUBLE_AT(offset) (((address)&locals[-((offset) + 1)])) + +#define SET_LOCALS_SLOT(value, offset) (*(intptr_t*)&locals[-(offset)] = *(intptr_t *)(value)) +#define SET_LOCALS_INT(value, offset) (*((jint *)&locals[-(offset)]) = (value)) +#define SET_LOCALS_DOUBLE(value, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->d = (value)) +#define SET_LOCALS_LONG(value, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->l = (value)) +#define SET_LOCALS_DOUBLE_FROM_ADDR(addr, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->d = \ + + +#endif // CPU_PPC_VM_BYTECODEINTERPRETER_PPC_PP diff --git a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.inline.hpp new file mode 100644 index 00000000000..01a9fb38c20 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.inline.hpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_BYTECODEINTERPRETER_PPC_INLINE_HPP +#define CPU_PPC_VM_BYTECODEINTERPRETER_PPC_INLINE_HPP + +#ifdef CC_INTERP + +// Inline interpreter functions for ppc. + +#include + +inline jfloat BytecodeInterpreter::VMfloatAdd(jfloat op1, jfloat op2) { return op1 + op2; } +inline jfloat BytecodeInterpreter::VMfloatSub(jfloat op1, jfloat op2) { return op1 - op2; } +inline jfloat BytecodeInterpreter::VMfloatMul(jfloat op1, jfloat op2) { return op1 * op2; } +inline jfloat BytecodeInterpreter::VMfloatDiv(jfloat op1, jfloat op2) { return op1 / op2; } +inline jfloat BytecodeInterpreter::VMfloatRem(jfloat op1, jfloat op2) { return (jfloat)fmod((double)op1, (double)op2); } + +inline jfloat BytecodeInterpreter::VMfloatNeg(jfloat op) { return -op; } + +inline int32_t BytecodeInterpreter::VMfloatCompare(jfloat op1, jfloat op2, int32_t direction) { + return ( op1 < op2 ? -1 : + op1 > op2 ? 1 : + op1 == op2 ? 0 : + (direction == -1 || direction == 1) ? direction : 0); + +} + +inline void BytecodeInterpreter::VMmemCopy64(uint32_t to[2], const uint32_t from[2]) { + to[0] = from[0]; to[1] = from[1]; +} + +// The long operations depend on compiler support for "long long" on ppc. + +inline jlong BytecodeInterpreter::VMlongAdd(jlong op1, jlong op2) { + return op1 + op2; +} + +inline jlong BytecodeInterpreter::VMlongAnd(jlong op1, jlong op2) { + return op1 & op2; +} + +inline jlong BytecodeInterpreter::VMlongDiv(jlong op1, jlong op2) { + if (op1 == min_jlong && op2 == -1) return op1; + return op1 / op2; +} + +inline jlong BytecodeInterpreter::VMlongMul(jlong op1, jlong op2) { + return op1 * op2; +} + +inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) { + return op1 | op2; +} + +inline jlong BytecodeInterpreter::VMlongSub(jlong op1, jlong op2) { + return op1 - op2; +} + +inline jlong BytecodeInterpreter::VMlongXor(jlong op1, jlong op2) { + return op1 ^ op2; +} + +inline jlong BytecodeInterpreter::VMlongRem(jlong op1, jlong op2) { + if (op1 == min_jlong && op2 == -1) return 0; + return op1 % op2; +} + +inline jlong BytecodeInterpreter::VMlongUshr(jlong op1, jint op2) { + return ((uint64_t) op1) >> (op2 & 0x3F); +} + +inline jlong BytecodeInterpreter::VMlongShr(jlong op1, jint op2) { + return op1 >> (op2 & 0x3F); +} + +inline jlong BytecodeInterpreter::VMlongShl(jlong op1, jint op2) { + return op1 << (op2 & 0x3F); +} + +inline jlong BytecodeInterpreter::VMlongNeg(jlong op) { + return -op; +} + +inline jlong BytecodeInterpreter::VMlongNot(jlong op) { + return ~op; +} + +inline int32_t BytecodeInterpreter::VMlongLtz(jlong op) { + return (op <= 0); +} + +inline int32_t BytecodeInterpreter::VMlongGez(jlong op) { + return (op >= 0); +} + +inline int32_t BytecodeInterpreter::VMlongEqz(jlong op) { + return (op == 0); +} + +inline int32_t BytecodeInterpreter::VMlongEq(jlong op1, jlong op2) { + return (op1 == op2); +} + +inline int32_t BytecodeInterpreter::VMlongNe(jlong op1, jlong op2) { + return (op1 != op2); +} + +inline int32_t BytecodeInterpreter::VMlongGe(jlong op1, jlong op2) { + return (op1 >= op2); +} + +inline int32_t BytecodeInterpreter::VMlongLe(jlong op1, jlong op2) { + return (op1 <= op2); +} + +inline int32_t BytecodeInterpreter::VMlongLt(jlong op1, jlong op2) { + return (op1 < op2); +} + +inline int32_t BytecodeInterpreter::VMlongGt(jlong op1, jlong op2) { + return (op1 > op2); +} + +inline int32_t BytecodeInterpreter::VMlongCompare(jlong op1, jlong op2) { + return (VMlongLt(op1, op2) ? -1 : VMlongGt(op1, op2) ? 1 : 0); +} + +// Long conversions + +inline jdouble BytecodeInterpreter::VMlong2Double(jlong val) { + return (jdouble) val; +} + +inline jfloat BytecodeInterpreter::VMlong2Float(jlong val) { + return (jfloat) val; +} + +inline jint BytecodeInterpreter::VMlong2Int(jlong val) { + return (jint) val; +} + +// Double Arithmetic + +inline jdouble BytecodeInterpreter::VMdoubleAdd(jdouble op1, jdouble op2) { + return op1 + op2; +} + +inline jdouble BytecodeInterpreter::VMdoubleDiv(jdouble op1, jdouble op2) { + return op1 / op2; +} + +inline jdouble BytecodeInterpreter::VMdoubleMul(jdouble op1, jdouble op2) { + return op1 * op2; +} + +inline jdouble BytecodeInterpreter::VMdoubleNeg(jdouble op) { + return -op; +} + +inline jdouble BytecodeInterpreter::VMdoubleRem(jdouble op1, jdouble op2) { + return fmod(op1, op2); +} + +inline jdouble BytecodeInterpreter::VMdoubleSub(jdouble op1, jdouble op2) { + return op1 - op2; +} + +inline int32_t BytecodeInterpreter::VMdoubleCompare(jdouble op1, jdouble op2, int32_t direction) { + return ( op1 < op2 ? -1 : + op1 > op2 ? 1 : + op1 == op2 ? 0 : + (direction == -1 || direction == 1) ? direction : 0); +} + +// Double Conversions + +inline jfloat BytecodeInterpreter::VMdouble2Float(jdouble val) { + return (jfloat) val; +} + +// Float Conversions + +inline jdouble BytecodeInterpreter::VMfloat2Double(jfloat op) { + return (jdouble) op; +} + +// Integer Arithmetic + +inline jint BytecodeInterpreter::VMintAdd(jint op1, jint op2) { + return op1 + op2; +} + +inline jint BytecodeInterpreter::VMintAnd(jint op1, jint op2) { + return op1 & op2; +} + +inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) { + /* it's possible we could catch this special case implicitly */ + if ((juint)op1 == 0x80000000 && op2 == -1) return op1; + else return op1 / op2; +} + +inline jint BytecodeInterpreter::VMintMul(jint op1, jint op2) { + return op1 * op2; +} + +inline jint BytecodeInterpreter::VMintNeg(jint op) { + return -op; +} + +inline jint BytecodeInterpreter::VMintOr(jint op1, jint op2) { + return op1 | op2; +} + +inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) { + /* it's possible we could catch this special case implicitly */ + if ((juint)op1 == 0x80000000 && op2 == -1) return 0; + else return op1 % op2; +} + +inline jint BytecodeInterpreter::VMintShl(jint op1, jint op2) { + return op1 << (op2 & 0x1f); +} + +inline jint BytecodeInterpreter::VMintShr(jint op1, jint op2) { + return op1 >> (op2 & 0x1f); +} + +inline jint BytecodeInterpreter::VMintSub(jint op1, jint op2) { + return op1 - op2; +} + +inline juint BytecodeInterpreter::VMintUshr(jint op1, jint op2) { + return ((juint) op1) >> (op2 & 0x1f); +} + +inline jint BytecodeInterpreter::VMintXor(jint op1, jint op2) { + return op1 ^ op2; +} + +inline jdouble BytecodeInterpreter::VMint2Double(jint val) { + return (jdouble) val; +} + +inline jfloat BytecodeInterpreter::VMint2Float(jint val) { + return (jfloat) val; +} + +inline jlong BytecodeInterpreter::VMint2Long(jint val) { + return (jlong) val; +} + +inline jchar BytecodeInterpreter::VMint2Char(jint val) { + return (jchar) val; +} + +inline jshort BytecodeInterpreter::VMint2Short(jint val) { + return (jshort) val; +} + +inline jbyte BytecodeInterpreter::VMint2Byte(jint val) { + return (jbyte) val; +} + +#endif // CC_INTERP + +#endif // CPU_PPC_VM_BYTECODEINTERPRETER_PPC_INLINE_HPP diff --git a/hotspot/src/cpu/ppc/vm/bytecodes_ppc.cpp b/hotspot/src/cpu/ppc/vm/bytecodes_ppc.cpp new file mode 100644 index 00000000000..6418951cee6 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/bytecodes_ppc.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "interpreter/bytecodes.hpp" + +void Bytecodes::pd_initialize() { + // No ppc specific initialization. +} diff --git a/hotspot/src/cpu/ppc/vm/bytecodes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytecodes_ppc.hpp new file mode 100644 index 00000000000..35fc51147a7 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/bytecodes_ppc.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_BYTECODES_PPC_HPP +#define CPU_PPC_VM_BYTECODES_PPC_HPP + +// No ppc64 specific bytecodes + +#endif // CPU_PPC_VM_BYTECODES_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp new file mode 100644 index 00000000000..507793037dc --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_BYTES_PPC_HPP +#define CPU_PPC_VM_BYTES_PPC_HPP + +#include "memory/allocation.hpp" + +class Bytes: AllStatic { + public: + // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering + // PowerPC needs to check for alignment. + + // can I count on address always being a pointer to an unsigned char? Yes + + // Returns true, if the byte ordering used by Java is different from the nativ byte ordering + // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. + static inline bool is_Java_byte_ordering_different() { return false; } + + // Thus, a swap between native and Java ordering is always a no-op: + static inline u2 swap_u2(u2 x) { return x; } + static inline u4 swap_u4(u4 x) { return x; } + static inline u8 swap_u8(u8 x) { return x; } + + static inline u2 get_native_u2(address p) { + return (intptr_t(p) & 1) == 0 + ? *(u2*)p + : ( u2(p[0]) << 8 ) + | ( u2(p[1]) ); + } + + static inline u4 get_native_u4(address p) { + switch (intptr_t(p) & 3) { + case 0: return *(u4*)p; + + case 2: return ( u4( ((u2*)p)[0] ) << 16 ) + | ( u4( ((u2*)p)[1] ) ); + + default: return ( u4(p[0]) << 24 ) + | ( u4(p[1]) << 16 ) + | ( u4(p[2]) << 8 ) + | u4(p[3]); + } + } + + static inline u8 get_native_u8(address p) { + switch (intptr_t(p) & 7) { + case 0: return *(u8*)p; + + case 4: return ( u8( ((u4*)p)[0] ) << 32 ) + | ( u8( ((u4*)p)[1] ) ); + + case 2: return ( u8( ((u2*)p)[0] ) << 48 ) + | ( u8( ((u2*)p)[1] ) << 32 ) + | ( u8( ((u2*)p)[2] ) << 16 ) + | ( u8( ((u2*)p)[3] ) ); + + default: return ( u8(p[0]) << 56 ) + | ( u8(p[1]) << 48 ) + | ( u8(p[2]) << 40 ) + | ( u8(p[3]) << 32 ) + | ( u8(p[4]) << 24 ) + | ( u8(p[5]) << 16 ) + | ( u8(p[6]) << 8 ) + | u8(p[7]); + } + } + + + + static inline void put_native_u2(address p, u2 x) { + if ( (intptr_t(p) & 1) == 0 ) { *(u2*)p = x; } + else { + p[0] = x >> 8; + p[1] = x; + } + } + + static inline void put_native_u4(address p, u4 x) { + switch ( intptr_t(p) & 3 ) { + case 0: *(u4*)p = x; + break; + + case 2: ((u2*)p)[0] = x >> 16; + ((u2*)p)[1] = x; + break; + + default: ((u1*)p)[0] = x >> 24; + ((u1*)p)[1] = x >> 16; + ((u1*)p)[2] = x >> 8; + ((u1*)p)[3] = x; + break; + } + } + + static inline void put_native_u8(address p, u8 x) { + switch ( intptr_t(p) & 7 ) { + case 0: *(u8*)p = x; + break; + + case 4: ((u4*)p)[0] = x >> 32; + ((u4*)p)[1] = x; + break; + + case 2: ((u2*)p)[0] = x >> 48; + ((u2*)p)[1] = x >> 32; + ((u2*)p)[2] = x >> 16; + ((u2*)p)[3] = x; + break; + + default: ((u1*)p)[0] = x >> 56; + ((u1*)p)[1] = x >> 48; + ((u1*)p)[2] = x >> 40; + ((u1*)p)[3] = x >> 32; + ((u1*)p)[4] = x >> 24; + ((u1*)p)[5] = x >> 16; + ((u1*)p)[6] = x >> 8; + ((u1*)p)[7] = x; + } + } + + + // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) + // (no byte-order reversal is needed since Power CPUs are big-endian oriented). + static inline u2 get_Java_u2(address p) { return get_native_u2(p); } + static inline u4 get_Java_u4(address p) { return get_native_u4(p); } + static inline u8 get_Java_u8(address p) { return get_native_u8(p); } + + static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, x); } + static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, x); } + static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, x); } +}; + +#endif // CPU_PPC_VM_BYTES_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/codeBuffer_ppc.hpp b/hotspot/src/cpu/ppc/vm/codeBuffer_ppc.hpp new file mode 100644 index 00000000000..1855aea1f29 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/codeBuffer_ppc.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_CODEBUFFER_PPC_HPP +#define CPU_PPC_VM_CODEBUFFER_PPC_HPP + +private: + void pd_initialize() {} + +public: + void flush_bundle(bool start_new_bundle) {} + +#endif // CPU_PPC_VM_CODEBUFFER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp new file mode 100644 index 00000000000..b24b3c4c895 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" +#include "code/icBuffer.hpp" +#include "code/nmethod.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/safepoint.hpp" +#ifdef COMPILER2 +#include "opto/matcher.hpp" +#endif + +// Release the CompiledICHolder* associated with this call site is there is one. +void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site) { + // This call site might have become stale so inspect it carefully. + NativeCall* call = nativeCall_at(call_site->addr()); + if (is_icholder_entry(call->destination())) { + NativeMovConstReg* value = nativeMovConstReg_at(call_site->cached_value()); + InlineCacheBuffer::queue_for_release((CompiledICHolder*)value->data()); + } +} + +bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) { + // This call site might have become stale so inspect it carefully. + NativeCall* call = nativeCall_at(call_site->addr()); + return is_icholder_entry(call->destination()); +} + +//----------------------------------------------------------------------------- +// High-level access to an inline cache. Guaranteed to be MT-safe. + +CompiledIC::CompiledIC(nmethod* nm, NativeCall* call) + : _ic_call(call) +{ + address ic_call = call->instruction_address(); + + assert(ic_call != NULL, "ic_call address must be set"); + assert(nm != NULL, "must pass nmethod"); + assert(nm->contains(ic_call), "must be in nmethod"); + + // Search for the ic_call at the given address. + RelocIterator iter(nm, ic_call, ic_call+1); + bool ret = iter.next(); + assert(ret == true, "relocInfo must exist at this address"); + assert(iter.addr() == ic_call, "must find ic_call"); + if (iter.type() == relocInfo::virtual_call_type) { + virtual_call_Relocation* r = iter.virtual_call_reloc(); + _is_optimized = false; + _value = nativeMovConstReg_at(r->cached_value()); + } else { + assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call"); + _is_optimized = true; + _value = NULL; + } +} + +// ---------------------------------------------------------------------------- + +// A PPC CompiledStaticCall looks like this: +// +// >>>> consts +// +// [call target1] +// [IC cache] +// [call target2] +// +// <<<< consts +// >>>> insts +// +// bl offset16 -+ -+ ??? // How many bits available? +// | | +// <<<< insts | | +// >>>> stubs | | +// | |- trampoline_stub_Reloc +// trampoline stub: | <-+ +// r2 = toc | +// r2 = [r2 + offset] | // Load call target1 from const section +// mtctr r2 | +// bctr |- static_stub_Reloc +// comp_to_interp_stub: <---+ +// r1 = toc +// ICreg = [r1 + IC_offset] // Load IC from const section +// r1 = [r1 + offset] // Load call target2 from const section +// mtctr r1 +// bctr +// +// <<<< stubs +// +// The call instruction in the code either +// - branches directly to a compiled method if offset encodable in instruction +// - branches to the trampoline stub if offset to compiled method not encodable +// - branches to the compiled_to_interp stub if target interpreted +// +// Further there are three relocations from the loads to the constants in +// the constant section. +// +// Usage of r1 and r2 in the stubs allows to distinguish them. + +const int IC_pos_in_java_to_interp_stub = 8; +#define __ _masm. +void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { +#ifdef COMPILER2 + // Get the mark within main instrs section which is set to the address of the call. + address call_addr = cbuf.insts_mark(); + + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a stub. + MacroAssembler _masm(&cbuf); + + // Start the stub. + address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); + if (stub == NULL) { + Compile::current()->env()->record_out_of_memory_failure(); + return; + } + + // For java_to_interp stubs we use R11_scratch1 as scratch register + // and in call trampoline stubs we use R12_scratch2. This way we + // can distinguish them (see is_NativeCallTrampolineStub_at()). + Register reg_scratch = R11_scratch1; + + // Create a static stub relocation which relates this stub + // with the call instruction at insts_call_instruction_offset in the + // instructions code-section. + __ relocate(static_stub_Relocation::spec(call_addr)); + const int stub_start_offset = __ offset(); + + // Now, create the stub's code: + // - load the TOC + // - load the inline cache oop from the constant pool + // - load the call target from the constant pool + // - call + __ calculate_address_from_global_toc(reg_scratch, __ method_toc()); + AddressLiteral ic = __ allocate_metadata_address((Metadata *)NULL); + __ load_const_from_method_toc(as_Register(Matcher::inline_cache_reg_encode()), ic, reg_scratch); + + if (ReoptimizeCallSequences) { + __ b64_patchable((address)-1, relocInfo::none); + } else { + AddressLiteral a((address)-1); + __ load_const_from_method_toc(reg_scratch, a, reg_scratch); + __ mtctr(reg_scratch); + __ bctr(); + } + + // FIXME: Assert that the stub can be identified and patched. + + // Java_to_interp_stub_size should be good. + assert((__ offset() - stub_start_offset) <= CompiledStaticCall::to_interp_stub_size(), + "should be good size"); + assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)), + "must not confuse java_to_interp with trampoline stubs"); + + // End the stub. + __ end_a_stub(); +#else + ShouldNotReachHere(); +#endif +} +#undef __ + +// Size of java_to_interp stub, this doesn't need to be accurate but it must +// be larger or equal to the real size of the stub. +// Used for optimization in Compile::Shorten_branches. +int CompiledStaticCall::to_interp_stub_size() { + return 12 * BytesPerInstWord; +} + +// Relocation entries for call stub, compiled java to interpreter. +// Used for optimization in Compile::Shorten_branches. +int CompiledStaticCall::reloc_to_interp_stub() { + return 5; +} + +void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) { + address stub = find_stub(); + guarantee(stub != NULL, "stub not found"); + + if (TraceICs) { + ResourceMark rm; + tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", + instruction_address(), + callee->name_and_sig_as_C_string()); + } + + // Creation also verifies the object. + NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + + assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(), + "a) MT-unsafe modification of inline cache"); + assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry, + "b) MT-unsafe modification of inline cache"); + + // Update stub. + method_holder->set_data((intptr_t)callee()); + jump->set_jump_destination(entry); + + // Update jump to call. + set_destination_mt_safe(stub); +} + +void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { + assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); + // Reset stub. + address stub = static_stub->addr(); + assert(stub != NULL, "stub not found"); + // Creation also verifies the object. + NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + method_holder->set_data(0); + jump->set_jump_destination((address)-1); +} + +//----------------------------------------------------------------------------- +// Non-product mode code +#ifndef PRODUCT + +void CompiledStaticCall::verify() { + // Verify call. + NativeCall::verify(); + if (os::is_MP()) { + verify_alignment(); + } + + // Verify stub. + address stub = find_stub(); + assert(stub != NULL, "no stub found for static call"); + // Creation also verifies the object. + NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + + // Verify state. + assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); +} + +#endif // !PRODUCT diff --git a/hotspot/src/cpu/ppc/vm/copy_ppc.hpp b/hotspot/src/cpu/ppc/vm/copy_ppc.hpp new file mode 100644 index 00000000000..61937be3e86 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/copy_ppc.hpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_COPY_PPC_HPP +#define CPU_PPC_VM_COPY_PPC_HPP + +#ifndef PPC64 +#error "copy currently only implemented for PPC64" +#endif + +// Inline functions for memory copy and fill. + +static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { + (void)memmove(to, from, count * HeapWordSize); +} + +static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: (void)memcpy(to, from, count * HeapWordSize); + break; + } +} + +static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) { + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: while (count-- > 0) { + *to++ = *from++; + } + break; + } +} + +static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { + (void)memmove(to, from, count * HeapWordSize); +} + +static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(void* from, void* to, size_t count) { + (void)memmove(to, from, count); +} + +static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) { + (void)memmove(to, from, count); +} + +// Template for atomic, element-wise copy. +template +static void copy_conjoint_atomic(T* from, T* to, size_t count) { + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } +} + +static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { + copy_conjoint_atomic(from, to, count); +} + +static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { + copy_conjoint_atomic(from, to, count); +} + +static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { + copy_conjoint_atomic(from, to, count); +} + +static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { + copy_conjoint_atomic(from, to, count); +} + +static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_bytes_atomic(from, to, count); +} + +static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count); +} + +static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jints_atomic((jint*)from, (jint*)to, count); +} + +static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count); +} + +static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); +} + +static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { + julong* to = (julong*)tohw; + julong v = ((julong)value << 32) | value; + while (count-- > 0) { + *to++ = v; + } +} + +static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { + pd_fill_to_words(tohw, count, value); +} + +static void pd_fill_to_bytes(void* to, size_t count, jubyte value) { + (void)memset(to, value, count); +} + +static void pd_zero_to_words(HeapWord* tohw, size_t count) { + pd_fill_to_words(tohw, count, 0); +} + +static void pd_zero_to_bytes(void* to, size_t count) { + (void)memset(to, 0, count); +} + +#endif // CPU_PPC_VM_COPY_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp b/hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp new file mode 100644 index 00000000000..6e43183ea3f --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP +#define CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP + + address generate_normal_entry(void); + address generate_native_entry(void); + + void lock_method(void); + void unlock_method(void); + + void generate_counter_incr(Label& overflow); + void generate_counter_overflow(Label& do_continue); + + void generate_more_monitors(); + void generate_deopt_handling(Register result_index); + + void generate_compute_interpreter_state(Label& exception_return); + +#endif // CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp new file mode 100644 index 00000000000..c21e55902f3 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp @@ -0,0 +1,3044 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "interpreter/bytecodeHistogram.hpp" +#include "interpreter/cppInterpreter.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterGenerator.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "oops/arrayOop.hpp" +#include "oops/methodData.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/arguments.hpp" +#include "runtime/deoptimization.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/timer.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" +#ifdef SHARK +#include "shark/shark_globals.hpp" +#endif + +#ifdef CC_INTERP + +#define __ _masm-> + +// Contains is used for identifying interpreter frames during a stack-walk. +// A frame with a PC in InterpretMethod must be identified as a normal C frame. +bool CppInterpreter::contains(address pc) { + return _code->contains(pc); +} + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +static address interpreter_frame_manager = NULL; +static address frame_manager_specialized_return = NULL; +static address native_entry = NULL; + +static address interpreter_return_address = NULL; + +static address unctrap_frame_manager_entry = NULL; + +static address deopt_frame_manager_return_atos = NULL; +static address deopt_frame_manager_return_btos = NULL; +static address deopt_frame_manager_return_itos = NULL; +static address deopt_frame_manager_return_ltos = NULL; +static address deopt_frame_manager_return_ftos = NULL; +static address deopt_frame_manager_return_dtos = NULL; +static address deopt_frame_manager_return_vtos = NULL; + +// A result handler converts/unboxes a native call result into +// a java interpreter/compiler result. The current frame is an +// interpreter frame. +address CppInterpreterGenerator::generate_result_handler_for(BasicType type) { + return AbstractInterpreterGenerator::generate_result_handler_for(type); +} + +// tosca based result to c++ interpreter stack based result. +address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType type) { + // + // A result is in the native abi result register from a native + // method call. We need to return this result to the interpreter by + // pushing the result on the interpreter's stack. + // + // Registers alive: + // R3_ARG1(R3_RET)/F1_ARG1(F1_RET) - result to move + // R4_ARG2 - address of tos + // LR + // + // Registers updated: + // R3_RET(R3_ARG1) - address of new tos (== R17_tos for T_VOID) + // + + int number_of_used_slots = 1; + + const Register tos = R4_ARG2; + Label done; + Label is_false; + + address entry = __ pc(); + + switch (type) { + case T_BOOLEAN: + __ cmpwi(CCR0, R3_RET, 0); + __ beq(CCR0, is_false); + __ li(R3_RET, 1); + __ stw(R3_RET, 0, tos); + __ b(done); + __ bind(is_false); + __ li(R3_RET, 0); + __ stw(R3_RET, 0, tos); + break; + case T_BYTE: + case T_CHAR: + case T_SHORT: + case T_INT: + __ stw(R3_RET, 0, tos); + break; + case T_LONG: + number_of_used_slots = 2; + // mark unused slot for debugging + // long goes to topmost slot + __ std(R3_RET, -BytesPerWord, tos); + __ li(R3_RET, 0); + __ std(R3_RET, 0, tos); + break; + case T_OBJECT: + __ verify_oop(R3_RET); + __ std(R3_RET, 0, tos); + break; + case T_FLOAT: + __ stfs(F1_RET, 0, tos); + break; + case T_DOUBLE: + number_of_used_slots = 2; + // mark unused slot for debugging + __ li(R3_RET, 0); + __ std(R3_RET, 0, tos); + // double goes to topmost slot + __ stfd(F1_RET, -BytesPerWord, tos); + break; + case T_VOID: + number_of_used_slots = 0; + break; + default: + ShouldNotReachHere(); + } + + __ BIND(done); + + // new expression stack top + __ addi(R3_RET, tos, -BytesPerWord * number_of_used_slots); + + __ blr(); + + return entry; +} + +address CppInterpreterGenerator::generate_stack_to_stack_converter(BasicType type) { + // + // Copy the result from the callee's stack to the caller's stack, + // caller and callee both being interpreted. + // + // Registers alive + // R3_ARG1 - address of callee's tos + BytesPerWord + // R4_ARG2 - address of caller's tos [i.e. free location] + // LR + // + // stack grows upwards, memory grows downwards. + // + // [ free ] <-- callee's tos + // [ optional result ] <-- R3_ARG1 + // [ optional dummy ] + // ... + // [ free ] <-- caller's tos, R4_ARG2 + // ... + // Registers updated + // R3_RET(R3_ARG1) - address of caller's new tos + // + // stack grows upwards, memory grows downwards. + // + // [ free ] <-- current tos, R3_RET + // [ optional result ] + // [ optional dummy ] + // ... + // + + const Register from = R3_ARG1; + const Register ret = R3_ARG1; + const Register tos = R4_ARG2; + const Register tmp1 = R21_tmp1; + const Register tmp2 = R22_tmp2; + + address entry = __ pc(); + + switch (type) { + case T_BOOLEAN: + case T_BYTE: + case T_CHAR: + case T_SHORT: + case T_INT: + case T_FLOAT: + __ lwz(tmp1, 0, from); + __ stw(tmp1, 0, tos); + // New expression stack top. + __ addi(ret, tos, - BytesPerWord); + break; + case T_LONG: + case T_DOUBLE: + // Move both entries for debug purposes even though only one is live. + __ ld(tmp1, BytesPerWord, from); + __ ld(tmp2, 0, from); + __ std(tmp1, 0, tos); + __ std(tmp2, -BytesPerWord, tos); + // New expression stack top. + __ addi(ret, tos, - 2 * BytesPerWord); // two slots + break; + case T_OBJECT: + __ ld(tmp1, 0, from); + __ verify_oop(tmp1); + __ std(tmp1, 0, tos); + // New expression stack top. + __ addi(ret, tos, - BytesPerWord); + break; + case T_VOID: + // New expression stack top. + __ mr(ret, tos); + break; + default: + ShouldNotReachHere(); + } + + __ blr(); + + return entry; +} + +address CppInterpreterGenerator::generate_stack_to_native_abi_converter(BasicType type) { + // + // Load a result from the callee's stack into the caller's expecting + // return register, callee being interpreted, caller being call stub + // or jit code. + // + // Registers alive + // R3_ARG1 - callee expression tos + BytesPerWord + // LR + // + // stack grows upwards, memory grows downwards. + // + // [ free ] <-- callee's tos + // [ optional result ] <-- R3_ARG1 + // [ optional dummy ] + // ... + // + // Registers updated + // R3_RET(R3_ARG1)/F1_RET - result + // + + const Register from = R3_ARG1; + const Register ret = R3_ARG1; + const FloatRegister fret = F1_ARG1; + + address entry = __ pc(); + + // Implemented uniformly for both kinds of endianness. The interpreter + // implements boolean, byte, char, and short as jint (4 bytes). + switch (type) { + case T_BOOLEAN: + case T_CHAR: + // zero extension + __ lwz(ret, 0, from); + break; + case T_BYTE: + case T_SHORT: + case T_INT: + // sign extension + __ lwa(ret, 0, from); + break; + case T_LONG: + __ ld(ret, 0, from); + break; + case T_OBJECT: + __ ld(ret, 0, from); + __ verify_oop(ret); + break; + case T_FLOAT: + __ lfs(fret, 0, from); + break; + case T_DOUBLE: + __ lfd(fret, 0, from); + break; + case T_VOID: + break; + default: + ShouldNotReachHere(); + } + + __ blr(); + + return entry; +} + +address CppInterpreter::return_entry(TosState state, int length) { + assert(interpreter_return_address != NULL, "Not initialized"); + return interpreter_return_address; +} + +address CppInterpreter::deopt_entry(TosState state, int length) { + address ret = NULL; + if (length != 0) { + switch (state) { + case atos: ret = deopt_frame_manager_return_atos; break; + case btos: ret = deopt_frame_manager_return_itos; break; + case ctos: + case stos: + case itos: ret = deopt_frame_manager_return_itos; break; + case ltos: ret = deopt_frame_manager_return_ltos; break; + case ftos: ret = deopt_frame_manager_return_ftos; break; + case dtos: ret = deopt_frame_manager_return_dtos; break; + case vtos: ret = deopt_frame_manager_return_vtos; break; + default: ShouldNotReachHere(); + } + } else { + ret = unctrap_frame_manager_entry; // re-execute the bytecode (e.g. uncommon trap, popframe) + } + assert(ret != NULL, "Not initialized"); + return ret; +} + +// +// Helpers for commoning out cases in the various type of method entries. +// + +// +// Registers alive +// R16_thread - JavaThread* +// R1_SP - old stack pointer +// R19_method - callee's Method +// R17_tos - address of caller's tos (prepushed) +// R15_prev_state - address of caller's BytecodeInterpreter or 0 +// return_pc in R21_tmp15 (only when called within generate_native_entry) +// +// Registers updated +// R14_state - address of callee's interpreter state +// R1_SP - new stack pointer +// CCR4_is_synced - current method is synchronized +// +void CppInterpreterGenerator::generate_compute_interpreter_state(Label& stack_overflow_return) { + // + // Stack layout at this point: + // + // F1 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // alignment (optional) + // [F1's outgoing Java arguments] <-- R17_tos + // ... + // F2 [PARENT_IJAVA_FRAME_ABI] + // ... + + //============================================================================= + // Allocate space for locals other than the parameters, the + // interpreter state, monitors, and the expression stack. + + const Register local_count = R21_tmp1; + const Register parameter_count = R22_tmp2; + const Register max_stack = R23_tmp3; + // Must not be overwritten within this method! + // const Register return_pc = R29_tmp9; + + const ConditionRegister is_synced = CCR4_is_synced; + const ConditionRegister is_native = CCR6; + const ConditionRegister is_static = CCR7; + + assert(is_synced != is_native, "condition code registers must be distinct"); + assert(is_synced != is_static, "condition code registers must be distinct"); + assert(is_native != is_static, "condition code registers must be distinct"); + + { + + // Local registers + const Register top_frame_size = R24_tmp4; + const Register access_flags = R25_tmp5; + const Register state_offset = R26_tmp6; + Register mem_stack_limit = R27_tmp7; + const Register page_size = R28_tmp8; + + BLOCK_COMMENT("compute_interpreter_state {"); + + // access_flags = method->access_flags(); + // TODO: PPC port: assert(4 == methodOopDesc::sz_access_flags(), "unexpected field size"); + __ lwa(access_flags, method_(access_flags)); + + // parameter_count = method->constMethod->size_of_parameters(); + // TODO: PPC port: assert(2 == ConstMethod::sz_size_of_parameters(), "unexpected field size"); + __ ld(max_stack, in_bytes(Method::const_offset()), R19_method); // Max_stack holds constMethod for a while. + __ lhz(parameter_count, in_bytes(ConstMethod::size_of_parameters_offset()), max_stack); + + // local_count = method->constMethod()->max_locals(); + // TODO: PPC port: assert(2 == ConstMethod::sz_max_locals(), "unexpected field size"); + __ lhz(local_count, in_bytes(ConstMethod::size_of_locals_offset()), max_stack); + + // max_stack = method->constMethod()->max_stack(); + // TODO: PPC port: assert(2 == ConstMethod::sz_max_stack(), "unexpected field size"); + __ lhz(max_stack, in_bytes(ConstMethod::max_stack_offset()), max_stack); + + if (EnableInvokeDynamic) { + // Take into account 'extra_stack_entries' needed by method handles (see method.hpp). + __ addi(max_stack, max_stack, Method::extra_stack_entries()); + } + + // mem_stack_limit = thread->stack_limit(); + __ ld(mem_stack_limit, thread_(stack_overflow_limit)); + + // Point locals at the first argument. Method's locals are the + // parameters on top of caller's expression stack. + + // tos points past last Java argument + __ sldi(R18_locals, parameter_count, Interpreter::logStackElementSize); + __ add(R18_locals, R17_tos, R18_locals); + + // R18_locals - i*BytesPerWord points to i-th Java local (i starts at 0) + + // Set is_native, is_synced, is_static - will be used later. + __ testbitdi(is_native, R0, access_flags, JVM_ACC_NATIVE_BIT); + __ testbitdi(is_synced, R0, access_flags, JVM_ACC_SYNCHRONIZED_BIT); + assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); + __ testbitdi(is_static, R0, access_flags, JVM_ACC_STATIC_BIT); + + // PARENT_IJAVA_FRAME_ABI + // + // frame_size = + // round_to((local_count - parameter_count)*BytesPerWord + + // 2*BytesPerWord + + // alignment + + // frame::interpreter_frame_cinterpreterstate_size_in_bytes() + // sizeof(PARENT_IJAVA_FRAME_ABI) + // method->is_synchronized() ? sizeof(BasicObjectLock) : 0 + + // max_stack*BytesPerWord, + // 16) + // + // Note that this calculation is exactly mirrored by + // AbstractInterpreter::layout_activation_impl() [ and + // AbstractInterpreter::size_activation() ]. Which is used by + // deoptimization so that it can allocate the proper sized + // frame. This only happens for interpreted frames so the extra + // notes below about max_stack below are not important. The other + // thing to note is that for interpreter frames other than the + // current activation the size of the stack is the size of the live + // portion of the stack at the particular bcp and NOT the maximum + // stack that the method might use. + // + // If we're calling a native method, we replace max_stack (which is + // zero) with space for the worst-case signature handler varargs + // vector, which is: + // + // max_stack = max(Argument::n_register_parameters, parameter_count+2); + // + // We add two slots to the parameter_count, one for the jni + // environment and one for a possible native mirror. We allocate + // space for at least the number of ABI registers, even though + // InterpreterRuntime::slow_signature_handler won't write more than + // parameter_count+2 words when it creates the varargs vector at the + // top of the stack. The generated slow signature handler will just + // load trash into registers beyond the necessary number. We're + // still going to cut the stack back by the ABI register parameter + // count so as to get SP+16 pointing at the ABI outgoing parameter + // area, so we need to allocate at least that much even though we're + // going to throw it away. + // + + // Adjust max_stack for native methods: + Label skip_native_calculate_max_stack; + __ bfalse(is_native, skip_native_calculate_max_stack); + // if (is_native) { + // max_stack = max(Argument::n_register_parameters, parameter_count+2); + __ addi(max_stack, parameter_count, 2*Interpreter::stackElementWords); + __ cmpwi(CCR0, max_stack, Argument::n_register_parameters); + __ bge(CCR0, skip_native_calculate_max_stack); + __ li(max_stack, Argument::n_register_parameters); + // } + __ bind(skip_native_calculate_max_stack); + // max_stack is now in bytes + __ slwi(max_stack, max_stack, Interpreter::logStackElementSize); + + // Calculate number of non-parameter locals (in slots): + Label not_java; + __ btrue(is_native, not_java); + // if (!is_native) { + // local_count = non-parameter local count + __ sub(local_count, local_count, parameter_count); + // } else { + // // nothing to do: method->max_locals() == 0 for native methods + // } + __ bind(not_java); + + + // Calculate top_frame_size and parent_frame_resize. + { + const Register parent_frame_resize = R12_scratch2; + + BLOCK_COMMENT("Compute top_frame_size."); + // top_frame_size = TOP_IJAVA_FRAME_ABI + // + size of interpreter state + __ li(top_frame_size, frame::top_ijava_frame_abi_size + + frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + // + max_stack + __ add(top_frame_size, top_frame_size, max_stack); + // + stack slots for a BasicObjectLock for synchronized methods + { + Label not_synced; + __ bfalse(is_synced, not_synced); + __ addi(top_frame_size, top_frame_size, frame::interpreter_frame_monitor_size_in_bytes()); + __ bind(not_synced); + } + // align + __ round_to(top_frame_size, frame::alignment_in_bytes); + + + BLOCK_COMMENT("Compute parent_frame_resize."); + // parent_frame_resize = R1_SP - R17_tos + __ sub(parent_frame_resize, R1_SP, R17_tos); + //__ li(parent_frame_resize, 0); + // + PARENT_IJAVA_FRAME_ABI + // + extra two slots for the no-parameter/no-locals + // method result + __ addi(parent_frame_resize, parent_frame_resize, + frame::parent_ijava_frame_abi_size + + 2*Interpreter::stackElementSize); + // + (locals_count - params_count) + __ sldi(R0, local_count, Interpreter::logStackElementSize); + __ add(parent_frame_resize, parent_frame_resize, R0); + // align + __ round_to(parent_frame_resize, frame::alignment_in_bytes); + + // + // Stack layout at this point: + // + // The new frame F0 hasn't yet been pushed, F1 is still the top frame. + // + // F0 [TOP_IJAVA_FRAME_ABI] + // alignment (optional) + // [F0's full operand stack] + // [F0's monitors] (optional) + // [F0's BytecodeInterpreter object] + // F1 [PARENT_IJAVA_FRAME_ABI] + // alignment (optional) + // [F0's Java result] + // [F0's non-arg Java locals] + // [F1's outgoing Java arguments] <-- R17_tos + // ... + // F2 [PARENT_IJAVA_FRAME_ABI] + // ... + + + // Calculate new R14_state + // and + // test that the new memory stack pointer is above the limit, + // throw a StackOverflowError otherwise. + __ sub(R11_scratch1/*F1's SP*/, R1_SP, parent_frame_resize); + __ addi(R14_state, R11_scratch1/*F1's SP*/, + -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + __ sub(R11_scratch1/*F0's SP*/, + R11_scratch1/*F1's SP*/, top_frame_size); + + BLOCK_COMMENT("Test for stack overflow:"); + __ cmpld(CCR0/*is_stack_overflow*/, R11_scratch1, mem_stack_limit); + __ blt(CCR0/*is_stack_overflow*/, stack_overflow_return); + + + //============================================================================= + // Frame_size doesn't overflow the stack. Allocate new frame and + // initialize interpreter state. + + // Register state + // + // R15 - local_count + // R16 - parameter_count + // R17 - max_stack + // + // R18 - frame_size + // R19 - access_flags + // CCR4_is_synced - is_synced + // + // GR_Lstate - pointer to the uninitialized new BytecodeInterpreter. + + // _last_Java_pc just needs to be close enough that we can identify + // the frame as an interpreted frame. It does not need to be the + // exact return address from either calling + // BytecodeInterpreter::InterpretMethod or the call to a jni native method. + // So we can initialize it here with a value of a bundle in this + // code fragment. We only do this initialization for java frames + // where InterpretMethod needs a a way to get a good pc value to + // store in the thread state. For interpreter frames used to call + // jni native code we just zero the value in the state and move an + // ip as needed in the native entry code. + // + // const Register last_Java_pc_addr = GR24_SCRATCH; // QQQ 27 + // const Register last_Java_pc = GR26_SCRATCH; + + // Must reference stack before setting new SP since Windows + // will not be able to deliver the exception on a bad SP. + // Windows also insists that we bang each page one at a time in order + // for the OS to map in the reserved pages. If we bang only + // the final page, Windows stops delivering exceptions to our + // VectoredExceptionHandler and terminates our program. + // Linux only requires a single bang but it's rare to have + // to bang more than 1 page so the code is enabled for both OS's. + + // BANG THE STACK + // + // Nothing to do for PPC, because updating the SP will automatically + // bang the page. + + // Up to here we have calculated the delta for the new C-frame and + // checked for a stack-overflow. Now we can savely update SP and + // resize the C-frame. + + // R14_state has already been calculated. + __ push_interpreter_frame(top_frame_size, parent_frame_resize, + R25_tmp5, R26_tmp6, R27_tmp7, R28_tmp8); + + } + + // + // Stack layout at this point: + // + // F0 has been been pushed! + // + // F0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // alignment (optional) (now it's here, if required) + // [F0's full operand stack] + // [F0's monitors] (optional) + // [F0's BytecodeInterpreter object] + // F1 [PARENT_IJAVA_FRAME_ABI] + // alignment (optional) (now it's here, if required) + // [F0's Java result] + // [F0's non-arg Java locals] + // [F1's outgoing Java arguments] + // ... + // F2 [PARENT_IJAVA_FRAME_ABI] + // ... + // + // R14_state points to F0's BytecodeInterpreter object. + // + + } + + //============================================================================= + // new BytecodeInterpreter-object is save, let's initialize it: + BLOCK_COMMENT("New BytecodeInterpreter-object is save."); + + { + // Locals + const Register bytecode_addr = R24_tmp4; + const Register constants = R25_tmp5; + const Register tos = R26_tmp6; + const Register stack_base = R27_tmp7; + const Register local_addr = R28_tmp8; + { + Label L; + __ btrue(is_native, L); + // if (!is_native) { + // bytecode_addr = constMethod->codes(); + __ ld(bytecode_addr, method_(const)); + __ addi(bytecode_addr, bytecode_addr, in_bytes(ConstMethod::codes_offset())); + // } + __ bind(L); + } + + __ ld(constants, in_bytes(Method::const_offset()), R19_method); + __ ld(constants, in_bytes(ConstMethod::constants_offset()), constants); + + // state->_prev_link = prev_state; + __ std(R15_prev_state, state_(_prev_link)); + + // For assertions only. + // TODO: not needed anyway because it coincides with `_monitor_base'. remove! + // state->_self_link = state; + DEBUG_ONLY(__ std(R14_state, state_(_self_link));) + + // state->_thread = thread; + __ std(R16_thread, state_(_thread)); + + // state->_method = method; + __ std(R19_method, state_(_method)); + + // state->_locals = locals; + __ std(R18_locals, state_(_locals)); + + // state->_oop_temp = NULL; + __ li(R0, 0); + __ std(R0, state_(_oop_temp)); + + // state->_last_Java_fp = *R1_SP // Use *R1_SP as fp + __ ld(R0, _abi(callers_sp), R1_SP); + __ std(R0, state_(_last_Java_fp)); + + BLOCK_COMMENT("load Stack base:"); + { + // Stack_base. + // if (!method->synchronized()) { + // stack_base = state; + // } else { + // stack_base = (uintptr_t)state - sizeof(BasicObjectLock); + // } + Label L; + __ mr(stack_base, R14_state); + __ bfalse(is_synced, L); + __ addi(stack_base, stack_base, -frame::interpreter_frame_monitor_size_in_bytes()); + __ bind(L); + } + + // state->_mdx = NULL; + __ li(R0, 0); + __ std(R0, state_(_mdx)); + + { + // if (method->is_native()) state->_bcp = NULL; + // else state->_bcp = bytecode_addr; + Label label1, label2; + __ bfalse(is_native, label1); + __ std(R0, state_(_bcp)); + __ b(label2); + __ bind(label1); + __ std(bytecode_addr, state_(_bcp)); + __ bind(label2); + } + + + // state->_result._to_call._callee = NULL; + __ std(R0, state_(_result._to_call._callee)); + + // state->_monitor_base = state; + __ std(R14_state, state_(_monitor_base)); + + // state->_msg = BytecodeInterpreter::method_entry; + __ li(R0, BytecodeInterpreter::method_entry); + __ stw(R0, state_(_msg)); + + // state->_last_Java_sp = R1_SP; + __ std(R1_SP, state_(_last_Java_sp)); + + // state->_stack_base = stack_base; + __ std(stack_base, state_(_stack_base)); + + // tos = stack_base - 1 slot (prepushed); + // state->_stack.Tos(tos); + __ addi(tos, stack_base, - Interpreter::stackElementSize); + __ std(tos, state_(_stack)); + + + { + BLOCK_COMMENT("get last_Java_pc:"); + // if (!is_native) state->_last_Java_pc = ; + // else state->_last_Java_pc = NULL; (just for neatness) + Label label1, label2; + __ btrue(is_native, label1); + __ get_PC_trash_LR(R0); + __ std(R0, state_(_last_Java_pc)); + __ b(label2); + __ bind(label1); + __ li(R0, 0); + __ std(R0, state_(_last_Java_pc)); + __ bind(label2); + } + + + // stack_limit = tos - max_stack; + __ sub(R0, tos, max_stack); + // state->_stack_limit = stack_limit; + __ std(R0, state_(_stack_limit)); + + + // cache = method->constants()->cache(); + __ ld(R0, ConstantPool::cache_offset_in_bytes(), constants); + // state->_constants = method->constants()->cache(); + __ std(R0, state_(_constants)); + + + + //============================================================================= + // synchronized method, allocate and initialize method object lock. + // if (!method->is_synchronized()) goto fill_locals_with_0x0s; + Label fill_locals_with_0x0s; + __ bfalse(is_synced, fill_locals_with_0x0s); + + // pool_holder = method->constants()->pool_holder(); + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + { + Label label1, label2; + // lockee = NULL; for java methods, correct value will be inserted in BytecodeInterpretMethod.hpp + __ li(R0,0); + __ bfalse(is_native, label2); + + __ bfalse(is_static, label1); + // if (method->is_static()) lockee = + // pool_holder->klass_part()->java_mirror(); + __ ld(R11_scratch1/*pool_holder*/, ConstantPool::pool_holder_offset_in_bytes(), constants); + __ ld(R0/*lockee*/, mirror_offset, R11_scratch1/*pool_holder*/); + __ b(label2); + + __ bind(label1); + // else lockee = *(oop*)locals; + __ ld(R0/*lockee*/, 0, R18_locals); + __ bind(label2); + + // monitor->set_obj(lockee); + __ std(R0/*lockee*/, BasicObjectLock::obj_offset_in_bytes(), stack_base); + } + + // See if we need to zero the locals + __ BIND(fill_locals_with_0x0s); + + + //============================================================================= + // fill locals with 0x0s + Label locals_zeroed; + __ btrue(is_native, locals_zeroed); + + if (true /* zerolocals */ || ClearInterpreterLocals) { + // local_count is already num_locals_slots - num_param_slots + __ sldi(R0, parameter_count, Interpreter::logStackElementSize); + __ sub(local_addr, R18_locals, R0); + __ cmpdi(CCR0, local_count, 0); + __ ble(CCR0, locals_zeroed); + + __ mtctr(local_count); + //__ ld_const_addr(R0, (address) 0xcafe0000babe); + __ li(R0, 0); + + Label zero_slot; + __ bind(zero_slot); + + // first local is at local_addr + __ std(R0, 0, local_addr); + __ addi(local_addr, local_addr, -BytesPerWord); + __ bdnz(zero_slot); + } + + __ BIND(locals_zeroed); + + } + BLOCK_COMMENT("} compute_interpreter_state"); +} + +// Generate code to initiate compilation on invocation counter overflow. +void CppInterpreterGenerator::generate_counter_overflow(Label& continue_entry) { + // Registers alive + // R14_state + // R16_thread + // + // Registers updated + // R14_state + // R3_ARG1 (=R3_RET) + // R4_ARG2 + + // After entering the vm we remove the activation and retry the + // entry point in case the compilation is complete. + + // InterpreterRuntime::frequency_counter_overflow takes one argument + // that indicates if the counter overflow occurs at a backwards + // branch (NULL bcp). We pass zero. The call returns the address + // of the verified entry point for the method or NULL if the + // compilation did not complete (either went background or bailed + // out). + __ li(R4_ARG2, 0); + + // Pass false to call_VM so it doesn't check for pending exceptions, + // since at this point in the method invocation the exception + // handler would try to exit the monitor of synchronized methods + // which haven't been entered yet. + // + // Returns verified_entry_point or NULL, we don't care which. + // + // Do not use the variant `frequency_counter_overflow' that returns + // a structure, because this will change the argument list by a + // hidden parameter (gcc 4.1). + + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), + R4_ARG2, + false); + // Returns verified_entry_point or NULL, we don't care which as we ignore it + // and run interpreted. + + // Reload method, it may have moved. + __ ld(R19_method, state_(_method)); + + // We jump now to the label "continue_after_compile". + __ b(continue_entry); +} + +// Increment invocation count and check for overflow. +// +// R19_method must contain Method* of method to profile. +void CppInterpreterGenerator::generate_counter_incr(Label& overflow) { + Label done; + const Register Rcounters = R12_scratch2; + const Register iv_be_count = R11_scratch1; + const Register invocation_limit = R12_scratch2; + const Register invocation_limit_addr = invocation_limit; + + // Load and ev. allocate MethodCounters object. + __ get_method_counters(R19_method, Rcounters, done); + + // Update standard invocation counters. + __ increment_invocation_counter(Rcounters, iv_be_count, R0); + + // Compare against limit. + BLOCK_COMMENT("Compare counter against limit:"); + assert(4 == sizeof(InvocationCounter::InterpreterInvocationLimit), + "must be 4 bytes"); + __ load_const(invocation_limit_addr, (address)&InvocationCounter::InterpreterInvocationLimit); + __ lwa(invocation_limit, 0, invocation_limit_addr); + __ cmpw(CCR0, iv_be_count, invocation_limit); + __ bge(CCR0, overflow); + __ bind(done); +} + +// +// Call a JNI method. +// +// Interpreter stub for calling a native method. (C++ interpreter) +// This sets up a somewhat different looking stack for calling the native method +// than the typical interpreter frame setup. +// +address CppInterpreterGenerator::generate_native_entry(void) { + if (native_entry != NULL) return native_entry; + address entry = __ pc(); + + // Read + // R16_thread + // R15_prev_state - address of caller's BytecodeInterpreter, if this snippet + // gets called by the frame manager. + // R19_method - callee's Method + // R17_tos - address of caller's tos + // R1_SP - caller's stack pointer + // R21_sender_SP - initial caller sp + // + // Update + // R14_state - address of caller's BytecodeInterpreter + // R3_RET - integer result, if any. + // F1_RET - float result, if any. + // + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // alignment (optional) + // [outgoing Java arguments] <-- R17_tos + // ... + // PARENT [PARENT_IJAVA_FRAME_ABI] + // ... + // + + const bool inc_counter = UseCompiler || CountCompiledCalls; + + const Register signature_handler_fd = R21_tmp1; + const Register pending_exception = R22_tmp2; + const Register result_handler_addr = R23_tmp3; + const Register native_method_fd = R24_tmp4; + const Register access_flags = R25_tmp5; + const Register active_handles = R26_tmp6; + const Register sync_state = R27_tmp7; + const Register sync_state_addr = sync_state; // Address is dead after use. + const Register suspend_flags = R24_tmp4; + + const Register return_pc = R28_tmp8; // Register will be locked for some time. + + const ConditionRegister is_synced = CCR4_is_synced; // Live-on-exit from compute_interpreter_state. + + + // R1_SP still points to caller's SP at this point. + + // Save initial_caller_sp to caller's abi. The caller frame must be + // resized before returning to get rid of the c2i arguments (if + // any). + // Override the saved SP with the senderSP so we can pop c2i + // arguments (if any) off when we return + __ std(R21_sender_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); + + // Save LR to caller's frame. We don't use _abi(lr) here, because it is not safe. + __ mflr(return_pc); + __ std(return_pc, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + + assert(return_pc->is_nonvolatile(), "return_pc must be a non-volatile register"); + + __ verify_method_ptr(R19_method); + + //============================================================================= + + // If this snippet gets called by the frame manager (at label + // `call_special'), then R15_prev_state is valid. If this snippet + // is not called by the frame manager, but e.g. by the call stub or + // by compiled code, then R15_prev_state is invalid. + { + // Set R15_prev_state to 0 if we don't return to the frame + // manager; we will return to the call_stub or to compiled code + // instead. If R15_prev_state is 0 there will be only one + // interpreter frame (we will set this up later) in this C frame! + // So we must take care about retrieving prev_state_(_prev_link) + // and restoring R1_SP when popping that interpreter. + Label prev_state_is_valid; + + __ load_const(R11_scratch1/*frame_manager_returnpc_addr*/, (address)&frame_manager_specialized_return); + __ ld(R12_scratch2/*frame_manager_returnpc*/, 0, R11_scratch1/*frame_manager_returnpc_addr*/); + __ cmpd(CCR0, return_pc, R12_scratch2/*frame_manager_returnpc*/); + __ beq(CCR0, prev_state_is_valid); + + __ li(R15_prev_state, 0); + + __ BIND(prev_state_is_valid); + } + + //============================================================================= + // Allocate new frame and initialize interpreter state. + + Label exception_return; + Label exception_return_sync_check; + Label stack_overflow_return; + + // Generate new interpreter state and jump to stack_overflow_return in case of + // a stack overflow. + generate_compute_interpreter_state(stack_overflow_return); + + //============================================================================= + // Increment invocation counter. On overflow, entry to JNI method + // will be compiled. + Label invocation_counter_overflow; + if (inc_counter) { + generate_counter_incr(invocation_counter_overflow); + } + + Label continue_after_compile; + __ BIND(continue_after_compile); + + // access_flags = method->access_flags(); + // Load access flags. + assert(access_flags->is_nonvolatile(), + "access_flags must be in a non-volatile register"); + // Type check. + // TODO: PPC port: assert(4 == methodOopDesc::sz_access_flags(), "unexpected field size"); + __ lwz(access_flags, method_(access_flags)); + + // We don't want to reload R19_method and access_flags after calls + // to some helper functions. + assert(R19_method->is_nonvolatile(), "R19_method must be a non-volatile register"); + + // Check for synchronized methods. Must happen AFTER invocation counter + // check, so method is not locked if counter overflows. + + { + Label method_is_not_synced; + // Is_synced is still alive. + assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); + __ bfalse(is_synced, method_is_not_synced); + + lock_method(); + // Reload method, it may have moved. + __ ld(R19_method, state_(_method)); + + __ BIND(method_is_not_synced); + } + + // jvmti/jvmpi support + __ notify_method_entry(); + + // Reload method, it may have moved. + __ ld(R19_method, state_(_method)); + + //============================================================================= + // Get and call the signature handler + + __ ld(signature_handler_fd, method_(signature_handler)); + Label call_signature_handler; + + __ cmpdi(CCR0, signature_handler_fd, 0); + __ bne(CCR0, call_signature_handler); + + // Method has never been called. Either generate a specialized + // handler or point to the slow one. + // + // Pass parameter 'false' to avoid exception check in call_VM. + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), R19_method, false); + + // Check for an exception while looking up the target method. If we + // incurred one, bail. + __ ld(pending_exception, thread_(pending_exception)); + __ cmpdi(CCR0, pending_exception, 0); + __ bne(CCR0, exception_return_sync_check); // has pending exception + + // reload method + __ ld(R19_method, state_(_method)); + + // Reload signature handler, it may have been created/assigned in the meanwhile + __ ld(signature_handler_fd, method_(signature_handler)); + + __ BIND(call_signature_handler); + + // Before we call the signature handler we push a new frame to + // protect the interpreter frame volatile registers when we return + // from jni but before we can get back to Java. + + // First set the frame anchor while the SP/FP registers are + // convenient and the slow signature handler can use this same frame + // anchor. + + // We have a TOP_IJAVA_FRAME here, which belongs to us. + __ set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R12_scratch2/*tmp*/); + + // Now the interpreter frame (and its call chain) have been + // invalidated and flushed. We are now protected against eager + // being enabled in native code. Even if it goes eager the + // registers will be reloaded as clean and we will invalidate after + // the call so no spurious flush should be possible. + + // Call signature handler and pass locals address. + // + // Our signature handlers copy required arguments to the C stack + // (outgoing C args), R3_ARG1 to R10_ARG8, and F1_ARG1 to + // F13_ARG13. + __ mr(R3_ARG1, R18_locals); + __ ld(signature_handler_fd, 0, signature_handler_fd); + __ call_stub(signature_handler_fd); + // reload method + __ ld(R19_method, state_(_method)); + + // Remove the register parameter varargs slots we allocated in + // compute_interpreter_state. SP+16 ends up pointing to the ABI + // outgoing argument area. + // + // Not needed on PPC64. + //__ add(SP, SP, Argument::n_register_parameters*BytesPerWord); + + assert(result_handler_addr->is_nonvolatile(), "result_handler_addr must be in a non-volatile register"); + // Save across call to native method. + __ mr(result_handler_addr, R3_RET); + + // Set up fixed parameters and call the native method. + // If the method is static, get mirror into R4_ARG2. + + { + Label method_is_not_static; + // access_flags is non-volatile and still, no need to restore it + + // restore access flags + __ testbitdi(CCR0, R0, access_flags, JVM_ACC_STATIC_BIT); + __ bfalse(CCR0, method_is_not_static); + + // constants = method->constants(); + __ ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); + __ ld(R11_scratch1/*constants*/, in_bytes(ConstMethod::constants_offset()), R11_scratch1); + // pool_holder = method->constants()->pool_holder(); + __ ld(R11_scratch1/*pool_holder*/, ConstantPool::pool_holder_offset_in_bytes(), + R11_scratch1/*constants*/); + + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + + // mirror = pool_holder->klass_part()->java_mirror(); + __ ld(R0/*mirror*/, mirror_offset, R11_scratch1/*pool_holder*/); + // state->_native_mirror = mirror; + __ std(R0/*mirror*/, state_(_oop_temp)); + // R4_ARG2 = &state->_oop_temp; + __ addir(R4_ARG2, state_(_oop_temp)); + + __ BIND(method_is_not_static); + } + + // At this point, arguments have been copied off the stack into + // their JNI positions. Oops are boxed in-place on the stack, with + // handles copied to arguments. The result handler address is in a + // register. + + // pass JNIEnv address as first parameter + __ addir(R3_ARG1, thread_(jni_environment)); + + // Load the native_method entry before we change the thread state. + __ ld(native_method_fd, method_(native_function)); + + //============================================================================= + // Transition from _thread_in_Java to _thread_in_native. As soon as + // we make this change the safepoint code needs to be certain that + // the last Java frame we established is good. The pc in that frame + // just needs to be near here not an actual return address. + + // We use release_store_fence to update values like the thread state, where + // we don't want the current thread to continue until all our prior memory + // accesses (including the new thread state) are visible to other threads. + __ li(R0, _thread_in_native); + __ release(); + + // TODO: PPC port: assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); + __ stw(R0, thread_(thread_state)); + + if (UseMembar) { + __ fence(); + } + + //============================================================================= + // Call the native method. Argument registers must not have been + // overwritten since "__ call_stub(signature_handler);" (except for + // ARG1 and ARG2 for static methods) + __ call_c(native_method_fd); + + __ std(R3_RET, state_(_native_lresult)); + __ stfd(F1_RET, state_(_native_fresult)); + + // The frame_manager_lr field, which we use for setting the last + // java frame, gets overwritten by the signature handler. Restore + // it now. + __ get_PC_trash_LR(R11_scratch1); + __ std(R11_scratch1, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + + // Because of GC R19_method may no longer be valid. + + // Block, if necessary, before resuming in _thread_in_Java state. + // In order for GC to work, don't clear the last_Java_sp until after + // blocking. + + + + //============================================================================= + // Switch thread to "native transition" state before reading the + // synchronization state. This additional state is necessary + // because reading and testing the synchronization state is not + // atomic w.r.t. GC, as this scenario demonstrates: Java thread A, + // in _thread_in_native state, loads _not_synchronized and is + // preempted. VM thread changes sync state to synchronizing and + // suspends threads for GC. Thread A is resumed to finish this + // native method, but doesn't block here since it didn't see any + // synchronization in progress, and escapes. + + // We use release_store_fence to update values like the thread state, where + // we don't want the current thread to continue until all our prior memory + // accesses (including the new thread state) are visible to other threads. + __ li(R0/*thread_state*/, _thread_in_native_trans); + __ release(); + __ stw(R0/*thread_state*/, thread_(thread_state)); + if (UseMembar) { + __ fence(); + } + // Write serialization page so that the VM thread can do a pseudo remote + // membar. We use the current thread pointer to calculate a thread + // specific offset to write to within the page. This minimizes bus + // traffic due to cache line collision. + else { + __ serialize_memory(R16_thread, R11_scratch1, R12_scratch2); + } + + // Now before we return to java we must look for a current safepoint + // (a new safepoint can not start since we entered native_trans). + // We must check here because a current safepoint could be modifying + // the callers registers right this moment. + + // Acquire isn't strictly necessary here because of the fence, but + // sync_state is declared to be volatile, so we do it anyway. + __ load_const(sync_state_addr, SafepointSynchronize::address_of_state()); + + // TODO: PPC port: assert(4 == SafepointSynchronize::sz_state(), "unexpected field size"); + __ lwz(sync_state, 0, sync_state_addr); + + // TODO: PPC port: assert(4 == Thread::sz_suspend_flags(), "unexpected field size"); + __ lwz(suspend_flags, thread_(suspend_flags)); + + __ acquire(); + + Label sync_check_done; + Label do_safepoint; + // No synchronization in progress nor yet synchronized + __ cmpwi(CCR0, sync_state, SafepointSynchronize::_not_synchronized); + // not suspended + __ cmpwi(CCR1, suspend_flags, 0); + + __ bne(CCR0, do_safepoint); + __ beq(CCR1, sync_check_done); + __ bind(do_safepoint); + // Block. We do the call directly and leave the current + // last_Java_frame setup undisturbed. We must save any possible + // native result acrosss the call. No oop is present + + __ mr(R3_ARG1, R16_thread); + __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans), + relocInfo::none); + __ bind(sync_check_done); + + //============================================================================= + // <<<<<< Back in Interpreter Frame >>>>> + + // We are in thread_in_native_trans here and back in the normal + // interpreter frame. We don't have to do anything special about + // safepoints and we can switch to Java mode anytime we are ready. + + // Note: frame::interpreter_frame_result has a dependency on how the + // method result is saved across the call to post_method_exit. For + // native methods it assumes that the non-FPU/non-void result is + // saved in _native_lresult and a FPU result in _native_fresult. If + // this changes then the interpreter_frame_result implementation + // will need to be updated too. + + // On PPC64, we have stored the result directly after the native call. + + //============================================================================= + // back in Java + + // We use release_store_fence to update values like the thread state, where + // we don't want the current thread to continue until all our prior memory + // accesses (including the new thread state) are visible to other threads. + __ li(R0/*thread_state*/, _thread_in_Java); + __ release(); + __ stw(R0/*thread_state*/, thread_(thread_state)); + if (UseMembar) { + __ fence(); + } + + __ reset_last_Java_frame(); + + // Reload GR27_method, call killed it. We can't look at + // state->_method until we're back in java state because in java + // state gc can't happen until we get to a safepoint. + // + // We've set thread_state to _thread_in_Java already, so restoring + // R19_method from R14_state works; R19_method is invalid, because + // GC may have happened. + __ ld(R19_method, state_(_method)); // reload method, may have moved + + // jvmdi/jvmpi support. Whether we've got an exception pending or + // not, and whether unlocking throws an exception or not, we notify + // on native method exit. If we do have an exception, we'll end up + // in the caller's context to handle it, so if we don't do the + // notify here, we'll drop it on the floor. + + __ notify_method_exit(true/*native method*/, + ilgl /*illegal state (not used for native methods)*/); + + + + //============================================================================= + // Handle exceptions + + // See if we must unlock. + // + { + Label method_is_not_synced; + // is_synced is still alive + assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); + __ bfalse(is_synced, method_is_not_synced); + + unlock_method(); + + __ bind(method_is_not_synced); + } + + // Reset active handles after returning from native. + // thread->active_handles()->clear(); + __ ld(active_handles, thread_(active_handles)); + // JNIHandleBlock::_top is an int. + // TODO: PPC port: assert(4 == JNIHandleBlock::top_size_in_bytes(), "unexpected field size"); + __ li(R0, 0); + __ stw(R0, JNIHandleBlock::top_offset_in_bytes(), active_handles); + + Label no_pending_exception_from_native_method; + __ ld(R0/*pending_exception*/, thread_(pending_exception)); + __ cmpdi(CCR0, R0/*pending_exception*/, 0); + __ beq(CCR0, no_pending_exception_from_native_method); + + + //----------------------------------------------------------------------------- + // An exception is pending. We call into the runtime only if the + // caller was not interpreted. If it was interpreted the + // interpreter will do the correct thing. If it isn't interpreted + // (call stub/compiled code) we will change our return and continue. + __ BIND(exception_return); + + Label return_to_initial_caller_with_pending_exception; + __ cmpdi(CCR0, R15_prev_state, 0); + __ beq(CCR0, return_to_initial_caller_with_pending_exception); + + // We are returning to an interpreter activation, just pop the state, + // pop our frame, leave the exception pending, and return. + __ pop_interpreter_state(/*prev_state_may_be_0=*/false); + __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); + __ mtlr(R21_tmp1); + __ blr(); + + __ BIND(exception_return_sync_check); + + assert(is_synced->is_nonvolatile(), "is_synced must be non-volatile"); + __ bfalse(is_synced, exception_return); + unlock_method(); + __ b(exception_return); + + + __ BIND(return_to_initial_caller_with_pending_exception); + // We are returning to a c2i-adapter / call-stub, get the address of the + // exception handler, pop the frame and return to the handler. + + // First, pop to caller's frame. + __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); + + __ push_frame_abi112(0, R11_scratch1); + // Get the address of the exception handler. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), + R16_thread, + R21_tmp1 /* return pc */); + __ pop_frame(); + + // Load the PC of the the exception handler into LR. + __ mtlr(R3_RET); + + // Load exception into R3_ARG1 and clear pending exception in thread. + __ ld(R3_ARG1/*exception*/, thread_(pending_exception)); + __ li(R4_ARG2, 0); + __ std(R4_ARG2, thread_(pending_exception)); + + // Load the original return pc into R4_ARG2. + __ mr(R4_ARG2/*issuing_pc*/, R21_tmp1); + + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + // Return to exception handler. + __ blr(); + + + //----------------------------------------------------------------------------- + // No exception pending. + __ BIND(no_pending_exception_from_native_method); + + // Move native method result back into proper registers and return. + // Invoke result handler (may unbox/promote). + __ ld(R3_RET, state_(_native_lresult)); + __ lfd(F1_RET, state_(_native_fresult)); + __ call_stub(result_handler_addr); + + // We have created a new BytecodeInterpreter object, now we must destroy it. + // + // Restore previous R14_state and caller's SP. R15_prev_state may + // be 0 here, because our caller may be the call_stub or compiled + // code. + __ pop_interpreter_state(/*prev_state_may_be_0=*/true); + __ pop_interpreter_frame(R11_scratch1, R12_scratch2, R21_tmp1 /* set to return pc */, R22_tmp2); + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + // Must use the return pc which was loaded from the caller's frame + // as the VM uses return-pc-patching for deoptimization. + __ mtlr(R21_tmp1); + __ blr(); + + + + //============================================================================= + // We encountered an exception while computing the interpreter + // state, so R14_state isn't valid. Act as if we just returned from + // the callee method with a pending exception. + __ BIND(stack_overflow_return); + + // + // Register state: + // R14_state invalid; trashed by compute_interpreter_state + // R15_prev_state valid, but may be 0 + // + // R1_SP valid, points to caller's SP; wasn't yet updated by + // compute_interpreter_state + // + + // Create exception oop and make it pending. + + // Throw the exception via RuntimeStub "throw_StackOverflowError_entry". + // + // Previously, we called C-Code directly. As a consequence, a + // possible GC tried to process the argument oops of the top frame + // (see RegisterMap::clear, which sets the corresponding flag to + // true). This lead to crashes because: + // 1. The top register map did not contain locations for the argument registers + // 2. The arguments are dead anyway, could be already overwritten in the worst case + // Solution: Call via special runtime stub that pushes it's own + // frame. This runtime stub has the flag "CodeBlob::caller_must_gc_arguments()" + // set to "false", what prevents the dead arguments getting GC'd. + // + // 2 cases exist: + // 1. We were called by the c2i adapter / call stub + // 2. We were called by the frame manager + // + // Both cases are handled by this code: + // 1. - initial_caller_sp was saved in both cases on entry, so it's safe to load it back even if it was not changed. + // - control flow will be: + // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->excp_blob of caller method + // 2. - control flow will be: + // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->rethrow_excp_entry of frame manager->resume_method + // Since we restored the caller SP above, the rethrow_excp_entry can restore the original interpreter state + // registers using the stack and resume the calling method with a pending excp. + + // Pop any c2i extension from the stack, restore LR just to be sure + __ ld(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + __ mtlr(R0); + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + // Load target address of the runtime stub. + __ load_const(R12_scratch2, (StubRoutines::throw_StackOverflowError_entry())); + __ mtctr(R12_scratch2); + __ bctr(); + + + //============================================================================= + // Counter overflow. + + if (inc_counter) { + // Handle invocation counter overflow + __ bind(invocation_counter_overflow); + + generate_counter_overflow(continue_after_compile); + } + + native_entry = entry; + return entry; +} + +bool AbstractInterpreter::can_be_compiled(methodHandle m) { + // No special entry points that preclude compilation. + return true; +} + +// Unlock the current method. +// +void CppInterpreterGenerator::unlock_method(void) { + // Find preallocated monitor and unlock method. Method monitor is + // the first one. + + // Registers alive + // R14_state + // + // Registers updated + // volatiles + // + const Register monitor = R4_ARG2; + + // Pass address of initial monitor we allocated. + // + // First monitor. + __ addi(monitor, R14_state, -frame::interpreter_frame_monitor_size_in_bytes()); + + // Unlock method + __ unlock_object(monitor); +} + +// Lock the current method. +// +void CppInterpreterGenerator::lock_method(void) { + // Find preallocated monitor and lock method. Method monitor is the + // first one. + + // + // Registers alive + // R14_state + // + // Registers updated + // volatiles + // + + const Register monitor = R4_ARG2; + const Register object = R5_ARG3; + + // Pass address of initial monitor we allocated. + __ addi(monitor, R14_state, -frame::interpreter_frame_monitor_size_in_bytes()); + + // Pass object address. + __ ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); + + // Lock method. + __ lock_object(monitor, object); +} + +// Generate code for handling resuming a deopted method. +void CppInterpreterGenerator::generate_deopt_handling(Register result_index) { + + //============================================================================= + // Returning from a compiled method into a deopted method. The + // bytecode at the bcp has completed. The result of the bytecode is + // in the native abi (the tosca for the template based + // interpreter). Any stack space that was used by the bytecode that + // has completed has been removed (e.g. parameters for an invoke) so + // all that we have to do is place any pending result on the + // expression stack and resume execution on the next bytecode. + + Label return_from_deopt_common; + + // R3_RET and F1_RET are live here! Load the array index of the + // required result stub address and continue at return_from_deopt_common. + + // Deopt needs to jump to here to enter the interpreter (return a result). + deopt_frame_manager_return_atos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_OBJECT)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_btos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_BOOLEAN)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_itos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_INT)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_ltos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_LONG)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_ftos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_FLOAT)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_dtos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); + __ b(return_from_deopt_common); + + deopt_frame_manager_return_vtos = __ pc(); + __ li(result_index, AbstractInterpreter::BasicType_as_index(T_VOID)); + // Last one, fall-through to return_from_deopt_common. + + // Deopt return common. An index is present that lets us move any + // possible result being return to the interpreter's stack. + // + __ BIND(return_from_deopt_common); + +} + +// Generate the code to handle a more_monitors message from the c++ interpreter. +void CppInterpreterGenerator::generate_more_monitors() { + + // + // Registers alive + // R16_thread - JavaThread* + // R15_prev_state - previous BytecodeInterpreter or 0 + // R14_state - BytecodeInterpreter* address of receiver's interpreter state + // R1_SP - old stack pointer + // + // Registers updated + // R1_SP - new stack pointer + // + + // Very-local scratch registers. + const Register old_tos = R21_tmp1; + const Register new_tos = R22_tmp2; + const Register stack_base = R23_tmp3; + const Register stack_limit = R24_tmp4; + const Register slot = R25_tmp5; + const Register n_slots = R25_tmp5; + + // Interpreter state fields. + const Register msg = R24_tmp4; + + // Load up relevant interpreter state. + + __ ld(stack_base, state_(_stack_base)); // Old stack_base + __ ld(old_tos, state_(_stack)); // Old tos + __ ld(stack_limit, state_(_stack_limit)); // Old stack_limit + + // extracted monitor_size + int monitor_size = frame::interpreter_frame_monitor_size_in_bytes(); + assert(Assembler::is_aligned((unsigned int)monitor_size, + (unsigned int)frame::alignment_in_bytes), + "size of a monitor must respect alignment of SP"); + + // Save and restore top LR + __ ld(R12_scratch2, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + __ resize_frame(-monitor_size, R11_scratch1);// Allocate space for new monitor + __ std(R12_scratch2, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + // Initial_caller_sp is used as unextended_sp for non initial callers. + __ std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); + __ addi(stack_base, stack_base, -monitor_size); // New stack_base + __ addi(new_tos, old_tos, -monitor_size); // New tos + __ addi(stack_limit, stack_limit, -monitor_size); // New stack_limit + + __ std(R1_SP, state_(_last_Java_sp)); // Update frame_bottom + + __ std(stack_base, state_(_stack_base)); // Update stack_base + __ std(new_tos, state_(_stack)); // Update tos + __ std(stack_limit, state_(_stack_limit)); // Update stack_limit + + __ li(msg, BytecodeInterpreter::got_monitors); // Tell interpreter we allocated the lock + __ stw(msg, state_(_msg)); + + // Shuffle expression stack down. Recall that stack_base points + // just above the new expression stack bottom. Old_tos and new_tos + // are used to scan thru the old and new expression stacks. + + Label copy_slot, copy_slot_finished; + __ sub(n_slots, stack_base, new_tos); + __ srdi_(n_slots, n_slots, LogBytesPerWord); // compute number of slots to copy + assert(LogBytesPerWord == 3, "conflicts assembler instructions"); + __ beq(CCR0, copy_slot_finished); // nothing to copy + + __ mtctr(n_slots); + + // loop + __ bind(copy_slot); + __ ldu(slot, BytesPerWord, old_tos); // slot = *++old_tos; + __ stdu(slot, BytesPerWord, new_tos); // *++new_tos = slot; + __ bdnz(copy_slot); + + __ bind(copy_slot_finished); + + // Restart interpreter + __ li(R0, 0); + __ std(R0, BasicObjectLock::obj_offset_in_bytes(), stack_base); // Mark lock as unused +} + +address CppInterpreterGenerator::generate_normal_entry(void) { + if (interpreter_frame_manager != NULL) return interpreter_frame_manager; + + address entry = __ pc(); + + address return_from_native_pc = (address) NULL; + + // Initial entry to frame manager (from call_stub or c2i_adapter) + + // + // Registers alive + // R16_thread - JavaThread* + // R19_method - callee's Method (method to be invoked) + // R17_tos - address of sender tos (prepushed) + // R1_SP - SP prepared by call stub such that caller's outgoing args are near top + // LR - return address to caller (call_stub or c2i_adapter) + // R21_sender_SP - initial caller sp + // + // Registers updated + // R15_prev_state - 0 + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // alignment (optional) + // [outgoing Java arguments] <-- R17_tos + // ... + // PARENT [PARENT_IJAVA_FRAME_ABI] + // ... + // + + // Save initial_caller_sp to caller's abi. + // The caller frame must be resized before returning to get rid of + // the c2i part on top of the calling compiled frame (if any). + // R21_tmp1 must match sender_sp in gen_c2i_adapter. + // Now override the saved SP with the senderSP so we can pop c2i + // arguments (if any) off when we return. + __ std(R21_sender_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); + + // Save LR to caller's frame. We don't use _abi(lr) here, + // because it is not safe. + __ mflr(R0); + __ std(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + + // If we come here, it is the first invocation of the frame manager. + // So there is no previous interpreter state. + __ li(R15_prev_state, 0); + + + // Fall through to where "recursive" invocations go. + + //============================================================================= + // Dispatch an instance of the interpreter. Recursive activations + // come here. + + Label re_dispatch; + __ BIND(re_dispatch); + + // + // Registers alive + // R16_thread - JavaThread* + // R19_method - callee's Method + // R17_tos - address of caller's tos (prepushed) + // R15_prev_state - address of caller's BytecodeInterpreter or 0 + // R1_SP - caller's SP trimmed such that caller's outgoing args are near top. + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] + // alignment (optional) + // [outgoing Java arguments] + // ... + // PARENT [PARENT_IJAVA_FRAME_ABI] + // ... + + // fall through to interpreted execution + + //============================================================================= + // Allocate a new Java frame and initialize the new interpreter state. + + Label stack_overflow_return; + + // Create a suitable new Java frame plus a new BytecodeInterpreter instance + // in the current (frame manager's) C frame. + generate_compute_interpreter_state(stack_overflow_return); + + // fall through + + //============================================================================= + // Interpreter dispatch. + + Label call_interpreter; + __ BIND(call_interpreter); + + // + // Registers alive + // R16_thread - JavaThread* + // R15_prev_state - previous BytecodeInterpreter or 0 + // R14_state - address of receiver's BytecodeInterpreter + // R1_SP - receiver's stack pointer + // + + // Thread fields. + const Register pending_exception = R21_tmp1; + + // Interpreter state fields. + const Register msg = R24_tmp4; + + // MethodOop fields. + const Register parameter_count = R25_tmp5; + const Register result_index = R26_tmp6; + + const Register dummy = R28_tmp8; + + // Address of various interpreter stubs. + // R29_tmp9 is reserved. + const Register stub_addr = R27_tmp7; + + // Uncommon trap needs to jump to here to enter the interpreter + // (re-execute current bytecode). + unctrap_frame_manager_entry = __ pc(); + + // If we are profiling, store our fp (BSP) in the thread so we can + // find it during a tick. + if (Arguments::has_profile()) { + // On PPC64 we store the pointer to the current BytecodeInterpreter, + // instead of the bsp of ia64. This should suffice to be able to + // find all interesting information. + __ std(R14_state, thread_(last_interpreter_fp)); + } + + // R16_thread, R14_state and R15_prev_state are nonvolatile + // registers. There is no need to save these. If we needed to save + // some state in the current Java frame, this could be a place to do + // so. + + // Call Java bytecode dispatcher passing "BytecodeInterpreter* istate". + __ call_VM_leaf(CAST_FROM_FN_PTR(address, + JvmtiExport::can_post_interpreter_events() + ? BytecodeInterpreter::runWithChecks + : BytecodeInterpreter::run), + R14_state); + + interpreter_return_address = __ last_calls_return_pc(); + + // R16_thread, R14_state and R15_prev_state have their values preserved. + + // If we are profiling, clear the fp in the thread to tell + // the profiler that we are no longer in the interpreter. + if (Arguments::has_profile()) { + __ li(R11_scratch1, 0); + __ std(R11_scratch1, thread_(last_interpreter_fp)); + } + + // Load message from bytecode dispatcher. + // TODO: PPC port: guarantee(4 == BytecodeInterpreter::sz_msg(), "unexpected field size"); + __ lwz(msg, state_(_msg)); + + + Label more_monitors; + Label return_from_native; + Label return_from_native_common; + Label return_from_native_no_exception; + Label return_from_interpreted_method; + Label return_from_recursive_activation; + Label unwind_recursive_activation; + Label resume_interpreter; + Label return_to_initial_caller; + Label unwind_initial_activation; + Label unwind_initial_activation_pending_exception; + Label call_method; + Label call_special; + Label retry_method; + Label retry_method_osr; + Label popping_frame; + Label throwing_exception; + + // Branch according to the received message + + __ cmpwi(CCR1, msg, BytecodeInterpreter::call_method); + __ cmpwi(CCR2, msg, BytecodeInterpreter::return_from_method); + + __ beq(CCR1, call_method); + __ beq(CCR2, return_from_interpreted_method); + + __ cmpwi(CCR3, msg, BytecodeInterpreter::more_monitors); + __ cmpwi(CCR4, msg, BytecodeInterpreter::throwing_exception); + + __ beq(CCR3, more_monitors); + __ beq(CCR4, throwing_exception); + + __ cmpwi(CCR5, msg, BytecodeInterpreter::popping_frame); + __ cmpwi(CCR6, msg, BytecodeInterpreter::do_osr); + + __ beq(CCR5, popping_frame); + __ beq(CCR6, retry_method_osr); + + __ stop("bad message from interpreter"); + + + //============================================================================= + // Add a monitor just below the existing one(s). State->_stack_base + // points to the lowest existing one, so we insert the new one just + // below it and shuffle the expression stack down. Ref. the above + // stack layout picture, we must update _stack_base, _stack, _stack_limit + // and _last_Java_sp in the interpreter state. + + __ BIND(more_monitors); + + generate_more_monitors(); + __ b(call_interpreter); + + generate_deopt_handling(result_index); + + // Restoring the R14_state is already done by the deopt_blob. + + // Current tos includes no parameter slots. + __ ld(R17_tos, state_(_stack)); + __ li(msg, BytecodeInterpreter::deopt_resume); + __ b(return_from_native_common); + + // We are sent here when we are unwinding from a native method or + // adapter with an exception pending. We need to notify the interpreter + // that there is an exception to process. + // We arrive here also if the frame manager called an (interpreted) target + // which returns with a StackOverflow exception. + // The control flow is in this case is: + // frame_manager->throw_excp_stub->forward_excp->rethrow_excp_entry + + AbstractInterpreter::_rethrow_exception_entry = __ pc(); + + // Restore R14_state. + __ ld(R14_state, 0, R1_SP); + __ addi(R14_state, R14_state, + -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + + // Store exception oop into thread object. + __ std(R3_RET, thread_(pending_exception)); + __ li(msg, BytecodeInterpreter::method_resume /*rethrow_exception*/); + // + // NOTE: the interpreter frame as setup be deopt does NOT include + // any parameter slots (good thing since we have no callee here + // and couldn't remove them) so we don't have to do any calculations + // here to figure it out. + // + __ ld(R17_tos, state_(_stack)); + __ b(return_from_native_common); + + + //============================================================================= + // Returning from a native method. Result is in the native abi + // location so we must move it to the java expression stack. + + __ BIND(return_from_native); + guarantee(return_from_native_pc == (address) NULL, "precondition"); + return_from_native_pc = __ pc(); + + // Restore R14_state. + __ ld(R14_state, 0, R1_SP); + __ addi(R14_state, R14_state, + -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + + // + // Registers alive + // R16_thread + // R14_state - address of caller's BytecodeInterpreter. + // R3_RET - integer result, if any. + // F1_RET - float result, if any. + // + // Registers updated + // R19_method - callee's Method + // R17_tos - caller's tos, with outgoing args popped + // result_index - index of result handler. + // msg - message for resuming interpreter. + // + + // Very-local scratch registers. + + const ConditionRegister have_pending_exception = CCR0; + + // Load callee Method, gc may have moved it. + __ ld(R19_method, state_(_result._to_call._callee)); + + // Load address of caller's tos. includes parameter slots. + __ ld(R17_tos, state_(_stack)); + + // Pop callee's parameters. + + __ ld(parameter_count, in_bytes(Method::const_offset()), R19_method); + __ lhz(parameter_count, in_bytes(ConstMethod::size_of_parameters_offset()), parameter_count); + __ sldi(parameter_count, parameter_count, Interpreter::logStackElementSize); + __ add(R17_tos, R17_tos, parameter_count); + + // Result stub address array index + // TODO: PPC port: assert(4 == methodOopDesc::sz_result_index(), "unexpected field size"); + __ lwa(result_index, method_(result_index)); + + __ li(msg, BytecodeInterpreter::method_resume); + + // + // Registers alive + // R16_thread + // R14_state - address of caller's BytecodeInterpreter. + // R17_tos - address of caller's tos with outgoing args already popped + // R3_RET - integer return value, if any. + // F1_RET - float return value, if any. + // result_index - index of result handler. + // msg - message for resuming interpreter. + // + // Registers updated + // R3_RET - new address of caller's tos, including result, if any + // + + __ BIND(return_from_native_common); + + // Check for pending exception + __ ld(pending_exception, thread_(pending_exception)); + __ cmpdi(CCR0, pending_exception, 0); + __ beq(CCR0, return_from_native_no_exception); + + // If there's a pending exception, we really have no result, so + // R3_RET is dead. Resume_interpreter assumes the new tos is in + // R3_RET. + __ mr(R3_RET, R17_tos); + // `resume_interpreter' expects R15_prev_state to be alive. + __ ld(R15_prev_state, state_(_prev_link)); + __ b(resume_interpreter); + + __ BIND(return_from_native_no_exception); + + // No pending exception, copy method result from native ABI register + // to tos. + + // Address of stub descriptor address array. + __ load_const(stub_addr, CppInterpreter::tosca_result_to_stack()); + + // Pass address of tos to stub. + __ mr(R4_ARG2, R17_tos); + + // Address of stub descriptor address. + __ sldi(result_index, result_index, LogBytesPerWord); + __ add(stub_addr, stub_addr, result_index); + + // Stub descriptor address. + __ ld(stub_addr, 0, stub_addr); + + // TODO: don't do this via a call, do it in place! + // + // call stub via descriptor + // in R3_ARG1/F1_ARG1: result value (R3_RET or F1_RET) + __ call_stub(stub_addr); + + // new tos = result of call in R3_RET + + // `resume_interpreter' expects R15_prev_state to be alive. + __ ld(R15_prev_state, state_(_prev_link)); + __ b(resume_interpreter); + + //============================================================================= + // We encountered an exception while computing the interpreter + // state, so R14_state isn't valid. Act as if we just returned from + // the callee method with a pending exception. + __ BIND(stack_overflow_return); + + // + // Registers alive + // R16_thread - JavaThread* + // R1_SP - old stack pointer + // R19_method - callee's Method + // R17_tos - address of caller's tos (prepushed) + // R15_prev_state - address of caller's BytecodeInterpreter or 0 + // R18_locals - address of callee's locals array + // + // Registers updated + // R3_RET - address of resuming tos, if recursive unwind + + Label Lskip_unextend_SP; + + { + const ConditionRegister is_initial_call = CCR0; + const Register tos_save = R21_tmp1; + const Register tmp = R22_tmp2; + + assert(tos_save->is_nonvolatile(), "need a nonvolatile"); + + // Is the exception thrown in the initial Java frame of this frame + // manager frame? + __ cmpdi(is_initial_call, R15_prev_state, 0); + __ bne(is_initial_call, Lskip_unextend_SP); + + // Pop any c2i extension from the stack. This is necessary in the + // non-recursive case (that is we were called by the c2i adapter, + // meaning we have to prev state). In this case we entered the frame + // manager through a special entry which pushes the orignal + // unextended SP to the stack. Here we load it back. + __ ld(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + __ mtlr(R0); + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + // Fall through + + __ bind(Lskip_unextend_SP); + + // Throw the exception via RuntimeStub "throw_StackOverflowError_entry". + // + // Previously, we called C-Code directly. As a consequence, a + // possible GC tried to process the argument oops of the top frame + // (see RegisterMap::clear, which sets the corresponding flag to + // true). This lead to crashes because: + // 1. The top register map did not contain locations for the argument registers + // 2. The arguments are dead anyway, could be already overwritten in the worst case + // Solution: Call via special runtime stub that pushes it's own frame. This runtime stub has the flag + // "CodeBlob::caller_must_gc_arguments()" set to "false", what prevents the dead arguments getting GC'd. + // + // 2 cases exist: + // 1. We were called by the c2i adapter / call stub + // 2. We were called by the frame manager + // + // Both cases are handled by this code: + // 1. - initial_caller_sp was saved on stack => Load it back and we're ok + // - control flow will be: + // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep->excp_blob of calling method + // 2. - control flow will be: + // throw_stackoverflow_stub->VM->throw_stackoverflow_stub->forward_excep-> + // ->rethrow_excp_entry of frame manager->resume_method + // Since we restored the caller SP above, the rethrow_excp_entry can restore the original interpreter state + // registers using the stack and resume the calling method with a pending excp. + + __ load_const(R3_ARG1, (StubRoutines::throw_StackOverflowError_entry())); + __ mtctr(R3_ARG1); + __ bctr(); + } + //============================================================================= + // We have popped a frame from an interpreted call. We are assured + // of returning to an interpreted call by the popframe abi. We have + // no return value all we have to do is pop the current frame and + // then make sure that the top of stack (of the caller) gets set to + // where it was when we entered the callee (i.e. the args are still + // in place). Or we are returning to the interpreter. In the first + // case we must extract result (if any) from the java expression + // stack and store it in the location the native abi would expect + // for a call returning this type. In the second case we must simply + // do a stack to stack move as we unwind. + + __ BIND(popping_frame); + + // Registers alive + // R14_state + // R15_prev_state + // R17_tos + // + // Registers updated + // R19_method + // R3_RET + // msg + { + Label L; + + // Reload callee method, gc may have moved it. + __ ld(R19_method, state_(_method)); + + // We may be returning to a deoptimized frame in which case the + // usual assumption of a recursive return is not true. + + // not equal = is recursive call + __ cmpdi(CCR0, R15_prev_state, 0); + + __ bne(CCR0, L); + + // Pop_frame capability. + // The pop_frame api says that the underlying frame is a Java frame, in this case + // (prev_state==null) it must be a compiled frame: + // + // Stack at this point: I, C2I + C, ... + // + // The outgoing arguments of the call have just been copied (popframe_preserve_args). + // By the pop_frame api, we must end up in an interpreted frame. So the compiled frame + // will be deoptimized. Deoptimization will restore the outgoing arguments from + // popframe_preserve_args, adjust the tos such that it includes the popframe_preserve_args, + // and adjust the bci such that the call will be executed again. + // We have no results, just pop the interpreter frame, resize the compiled frame to get rid + // of the c2i extension and return to the deopt_handler. + __ b(unwind_initial_activation); + + // is recursive call + __ bind(L); + + // Resume_interpreter expects the original tos in R3_RET. + __ ld(R3_RET, prev_state_(_stack)); + + // We're done. + __ li(msg, BytecodeInterpreter::popping_frame); + + __ b(unwind_recursive_activation); + } + + + //============================================================================= + + // We have finished an interpreted call. We are either returning to + // native (call_stub/c2) or we are returning to the interpreter. + // When returning to native, we must extract the result (if any) + // from the java expression stack and store it in the location the + // native abi expects. When returning to the interpreter we must + // simply do a stack to stack move as we unwind. + + __ BIND(return_from_interpreted_method); + + // + // Registers alive + // R16_thread - JavaThread* + // R15_prev_state - address of caller's BytecodeInterpreter or 0 + // R14_state - address of callee's interpreter state + // R1_SP - callee's stack pointer + // + // Registers updated + // R19_method - callee's method + // R3_RET - address of result (new caller's tos), + // + // if returning to interpreted + // msg - message for interpreter, + // if returning to interpreted + // + + // Check if this is the initial invocation of the frame manager. + // If so, R15_prev_state will be null. + __ cmpdi(CCR0, R15_prev_state, 0); + + // Reload callee method, gc may have moved it. + __ ld(R19_method, state_(_method)); + + // Load the method's result type. + __ lwz(result_index, method_(result_index)); + + // Go to return_to_initial_caller if R15_prev_state is null. + __ beq(CCR0, return_to_initial_caller); + + // Copy callee's result to caller's expression stack via inline stack-to-stack + // converters. + { + Register new_tos = R3_RET; + Register from_temp = R4_ARG2; + Register from = R5_ARG3; + Register tos = R6_ARG4; + Register tmp1 = R7_ARG5; + Register tmp2 = R8_ARG6; + + ConditionRegister result_type_is_void = CCR1; + ConditionRegister result_type_is_long = CCR2; + ConditionRegister result_type_is_double = CCR3; + + Label stack_to_stack_void; + Label stack_to_stack_double_slot; // T_LONG, T_DOUBLE + Label stack_to_stack_single_slot; // T_BOOLEAN, T_BYTE, T_CHAR, T_SHORT, T_INT, T_FLOAT, T_OBJECT + Label stack_to_stack_done; + + // Pass callee's address of tos + BytesPerWord + __ ld(from_temp, state_(_stack)); + + // result type: void + __ cmpwi(result_type_is_void, result_index, AbstractInterpreter::BasicType_as_index(T_VOID)); + + // Pass caller's tos == callee's locals address + __ ld(tos, state_(_locals)); + + // result type: long + __ cmpwi(result_type_is_long, result_index, AbstractInterpreter::BasicType_as_index(T_LONG)); + + __ addi(from, from_temp, Interpreter::stackElementSize); + + // !! don't branch above this line !! + + // handle void + __ beq(result_type_is_void, stack_to_stack_void); + + // result type: double + __ cmpwi(result_type_is_double, result_index, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); + + // handle long or double + __ beq(result_type_is_long, stack_to_stack_double_slot); + __ beq(result_type_is_double, stack_to_stack_double_slot); + + // fall through to single slot types (incl. object) + + { + __ BIND(stack_to_stack_single_slot); + // T_BOOLEAN, T_BYTE, T_CHAR, T_SHORT, T_INT, T_FLOAT, T_OBJECT + + __ ld(tmp1, 0, from); + __ std(tmp1, 0, tos); + // New expression stack top + __ addi(new_tos, tos, - BytesPerWord); + + __ b(stack_to_stack_done); + } + + { + __ BIND(stack_to_stack_double_slot); + // T_LONG, T_DOUBLE + + // Move both entries for debug purposes even though only one is live + __ ld(tmp1, BytesPerWord, from); + __ ld(tmp2, 0, from); + __ std(tmp1, 0, tos); + __ std(tmp2, -BytesPerWord, tos); + + // new expression stack top + __ addi(new_tos, tos, - 2 * BytesPerWord); // two slots + __ b(stack_to_stack_done); + } + + { + __ BIND(stack_to_stack_void); + // T_VOID + + // new expression stack top + __ mr(new_tos, tos); + // fall through to stack_to_stack_done + } + + __ BIND(stack_to_stack_done); + } + + // new tos = R3_RET + + // Get the message for the interpreter + __ li(msg, BytecodeInterpreter::method_resume); + + // And fall thru + + + //============================================================================= + // Restore caller's interpreter state and pass pointer to caller's + // new tos to caller. + + __ BIND(unwind_recursive_activation); + + // + // Registers alive + // R15_prev_state - address of caller's BytecodeInterpreter + // R3_RET - address of caller's tos + // msg - message for caller's BytecodeInterpreter + // R1_SP - callee's stack pointer + // + // Registers updated + // R14_state - address of caller's BytecodeInterpreter + // R15_prev_state - address of its parent or 0 + // + + // Pop callee's interpreter and set R14_state to caller's interpreter. + __ pop_interpreter_state(/*prev_state_may_be_0=*/false); + + // And fall thru + + + //============================================================================= + // Resume the (calling) interpreter after a call. + + __ BIND(resume_interpreter); + + // + // Registers alive + // R14_state - address of resuming BytecodeInterpreter + // R15_prev_state - address of its parent or 0 + // R3_RET - address of resuming tos + // msg - message for resuming interpreter + // R1_SP - callee's stack pointer + // + // Registers updated + // R1_SP - caller's stack pointer + // + + // Restore C stack pointer of caller (resuming interpreter), + // R14_state already points to the resuming BytecodeInterpreter. + __ pop_interpreter_frame_to_state(R14_state, R21_tmp1, R11_scratch1, R12_scratch2); + + // Store new address of tos (holding return value) in interpreter state. + __ std(R3_RET, state_(_stack)); + + // Store message for interpreter. + __ stw(msg, state_(_msg)); + + __ b(call_interpreter); + + //============================================================================= + // Interpreter returning to native code (call_stub/c1/c2) from + // initial activation. Convert stack result and unwind activation. + + __ BIND(return_to_initial_caller); + + // + // Registers alive + // R19_method - callee's Method + // R14_state - address of callee's interpreter state + // R16_thread - JavaThread + // R1_SP - callee's stack pointer + // + // Registers updated + // R3_RET/F1_RET - result in expected output register + // + + // If we have an exception pending we have no result and we + // must figure out where to really return to. + // + __ ld(pending_exception, thread_(pending_exception)); + __ cmpdi(CCR0, pending_exception, 0); + __ bne(CCR0, unwind_initial_activation_pending_exception); + + __ lwa(result_index, method_(result_index)); + + // Address of stub descriptor address array. + __ load_const(stub_addr, CppInterpreter::stack_result_to_native()); + + // Pass address of callee's tos + BytesPerWord. + // Will then point directly to result. + __ ld(R3_ARG1, state_(_stack)); + __ addi(R3_ARG1, R3_ARG1, Interpreter::stackElementSize); + + // Address of stub descriptor address + __ sldi(result_index, result_index, LogBytesPerWord); + __ add(stub_addr, stub_addr, result_index); + + // Stub descriptor address + __ ld(stub_addr, 0, stub_addr); + + // TODO: don't do this via a call, do it in place! + // + // call stub via descriptor + __ call_stub(stub_addr); + + __ BIND(unwind_initial_activation); + + // Unwind from initial activation. No exception is pending. + + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // ... + // CALLER [PARENT_IJAVA_FRAME_ABI] + // ... + // CALLER [unextended ABI] + // ... + // + // The CALLER frame has a C2I adapter or is an entry-frame. + // + + // An interpreter frame exists, we may pop the TOP_IJAVA_FRAME and + // turn the caller's PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. + // But, we simply restore the return pc from the caller's frame and + // use the caller's initial_caller_sp as the new SP which pops the + // interpreter frame and "resizes" the caller's frame to its "unextended" + // size. + + // get rid of top frame + __ pop_frame(); + + // Load return PC from parent frame. + __ ld(R21_tmp1, _parent_ijava_frame_abi(lr), R1_SP); + + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + // update LR + __ mtlr(R21_tmp1); + + // return + __ blr(); + + //============================================================================= + // Unwind from initial activation. An exception is pending + + __ BIND(unwind_initial_activation_pending_exception); + + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // ... + // CALLER [PARENT_IJAVA_FRAME_ABI] + // ... + // CALLER [unextended ABI] + // ... + // + // The CALLER frame has a C2I adapter or is an entry-frame. + // + + // An interpreter frame exists, we may pop the TOP_IJAVA_FRAME and + // turn the caller's PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. + // But, we just pop the current TOP_IJAVA_FRAME and fall through + + __ pop_frame(); + __ ld(R3_ARG1, _top_ijava_frame_abi(lr), R1_SP); + + // + // Stack layout at this point: + // + // CALLER [PARENT_IJAVA_FRAME_ABI] <-- R1_SP + // ... + // CALLER [unextended ABI] + // ... + // + // The CALLER frame has a C2I adapter or is an entry-frame. + // + // Registers alive + // R16_thread + // R3_ARG1 - return address to caller + // + // Registers updated + // R3_ARG1 - address of pending exception + // R4_ARG2 - issuing pc = return address to caller + // LR - address of exception handler stub + // + + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + __ mr(R14, R3_ARG1); // R14 := ARG1 + __ mr(R4_ARG2, R3_ARG1); // ARG2 := ARG1 + + // Find the address of the "catch_exception" stub. + __ push_frame_abi112(0, R11_scratch1); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), + R16_thread, + R4_ARG2); + __ pop_frame(); + + // Load continuation address into LR. + __ mtlr(R3_RET); + + // Load address of pending exception and clear it in thread object. + __ ld(R3_ARG1/*R3_RET*/, thread_(pending_exception)); + __ li(R4_ARG2, 0); + __ std(R4_ARG2, thread_(pending_exception)); + + // re-load issuing pc + __ mr(R4_ARG2, R14); + + // Branch to found exception handler. + __ blr(); + + //============================================================================= + // Call a new method. Compute new args and trim the expression stack + // to only what we are currently using and then recurse. + + __ BIND(call_method); + + // + // Registers alive + // R16_thread + // R14_state - address of caller's BytecodeInterpreter + // R1_SP - caller's stack pointer + // + // Registers updated + // R15_prev_state - address of caller's BytecodeInterpreter + // R17_tos - address of caller's tos + // R19_method - callee's Method + // R1_SP - trimmed back + // + + // Very-local scratch registers. + + const Register offset = R21_tmp1; + const Register tmp = R22_tmp2; + const Register self_entry = R23_tmp3; + const Register stub_entry = R24_tmp4; + + const ConditionRegister cr = CCR0; + + // Load the address of the frame manager. + __ load_const(self_entry, &interpreter_frame_manager); + __ ld(self_entry, 0, self_entry); + + // Load BytecodeInterpreter._result._to_call._callee (callee's Method). + __ ld(R19_method, state_(_result._to_call._callee)); + // Load BytecodeInterpreter._stack (outgoing tos). + __ ld(R17_tos, state_(_stack)); + + // Save address of caller's BytecodeInterpreter. + __ mr(R15_prev_state, R14_state); + + // Load the callee's entry point. + // Load BytecodeInterpreter._result._to_call._callee_entry_point. + __ ld(stub_entry, state_(_result._to_call._callee_entry_point)); + + // Check whether stub_entry is equal to self_entry. + __ cmpd(cr, self_entry, stub_entry); + // if (self_entry == stub_entry) + // do a re-dispatch + __ beq(cr, re_dispatch); + // else + // call the specialized entry (adapter for jni or compiled code) + __ BIND(call_special); + + // + // Call the entry generated by `InterpreterGenerator::generate_native_entry'. + // + // Registers alive + // R16_thread + // R15_prev_state - address of caller's BytecodeInterpreter + // R19_method - callee's Method + // R17_tos - address of caller's tos + // R1_SP - caller's stack pointer + // + + // Mark return from specialized entry for generate_native_entry. + guarantee(return_from_native_pc != (address) NULL, "precondition"); + frame_manager_specialized_return = return_from_native_pc; + + // Set sender_SP in case we call interpreter native wrapper which + // will expect it. Compiled code should not care. + __ mr(R21_sender_SP, R1_SP); + + // Do a tail call here, and let the link register point to + // frame_manager_specialized_return which is return_from_native_pc. + __ load_const(tmp, frame_manager_specialized_return); + __ call_stub_and_return_to(stub_entry, tmp /* return_pc=tmp */); + + + //============================================================================= + // + // InterpretMethod triggered OSR compilation of some Java method M + // and now asks to run the compiled code. We call this code the + // `callee'. + // + // This is our current idea on how OSR should look like on PPC64: + // + // While interpreting a Java method M the stack is: + // + // (InterpretMethod (M), IJAVA_FRAME (M), ANY_FRAME, ...). + // + // After having OSR compiled M, `InterpretMethod' returns to the + // frame manager, sending the message `retry_method_osr'. The stack + // is: + // + // (IJAVA_FRAME (M), ANY_FRAME, ...). + // + // The compiler will have generated an `nmethod' suitable for + // continuing execution of M at the bytecode index at which OSR took + // place. So now the frame manager calls the OSR entry. The OSR + // entry sets up a JIT_FRAME for M and continues execution of M with + // initial state determined by the IJAVA_FRAME. + // + // (JIT_FRAME (M), IJAVA_FRAME (M), ANY_FRAME, ...). + // + + __ BIND(retry_method_osr); + { + // + // Registers alive + // R16_thread + // R15_prev_state - address of caller's BytecodeInterpreter + // R14_state - address of callee's BytecodeInterpreter + // R1_SP - callee's SP before call to InterpretMethod + // + // Registers updated + // R17 - pointer to callee's locals array + // (declared via `interpreter_arg_ptr_reg' in the AD file) + // R19_method - callee's Method + // R1_SP - callee's SP (will become SP of OSR adapter frame) + // + + // Provide a debugger breakpoint in the frame manager if breakpoints + // in osr'd methods are requested. +#ifdef COMPILER2 + NOT_PRODUCT( if (OptoBreakpointOSR) { __ illtrap(); } ) +#endif + + // Load callee's pointer to locals array from callee's state. + // __ ld(R17, state_(_locals)); + + // Load osr entry. + __ ld(R12_scratch2, state_(_result._osr._osr_entry)); + + // Load address of temporary osr buffer to arg1. + __ ld(R3_ARG1, state_(_result._osr._osr_buf)); + __ mtctr(R12_scratch2); + + // Load method oop, gc may move it during execution of osr'd method. + __ ld(R22_tmp2, state_(_method)); + // Load message 'call_method'. + __ li(R23_tmp3, BytecodeInterpreter::call_method); + + { + // Pop the IJAVA frame of the method which we are going to call osr'd. + Label no_state, skip_no_state; + __ pop_interpreter_state(/*prev_state_may_be_0=*/true); + __ cmpdi(CCR0, R14_state,0); + __ beq(CCR0, no_state); + // return to interpreter + __ pop_interpreter_frame_to_state(R14_state, R11_scratch1, R12_scratch2, R21_tmp1); + + // Init _result._to_call._callee and tell gc that it contains a valid oop + // by setting _msg to 'call_method'. + __ std(R22_tmp2, state_(_result._to_call._callee)); + // TODO: PPC port: assert(4 == BytecodeInterpreter::sz_msg(), "unexpected field size"); + __ stw(R23_tmp3, state_(_msg)); + + __ load_const(R21_tmp1, frame_manager_specialized_return); + __ b(skip_no_state); + __ bind(no_state); + + // Return to initial caller. + + // Get rid of top frame. + __ pop_frame(); + + // Load return PC from parent frame. + __ ld(R21_tmp1, _parent_ijava_frame_abi(lr), R1_SP); + + // Resize frame to get rid of a potential extension. + __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + + __ bind(skip_no_state); + + // Update LR with return pc. + __ mtlr(R21_tmp1); + } + // Jump to the osr entry point. + __ bctr(); + + } + + //============================================================================= + // Interpreted method "returned" with an exception, pass it on. + // Pass no result, unwind activation and continue/return to + // interpreter/call_stub/c2. + + __ BIND(throwing_exception); + + // Check if this is the initial invocation of the frame manager. If + // so, previous interpreter state in R15_prev_state will be null. + + // New tos of caller is callee's first parameter address, that is + // callee's incoming arguments are popped. + __ ld(R3_RET, state_(_locals)); + + // Check whether this is an initial call. + __ cmpdi(CCR0, R15_prev_state, 0); + // Yes, called from the call stub or from generated code via a c2i frame. + __ beq(CCR0, unwind_initial_activation_pending_exception); + + // Send resume message, interpreter will see the exception first. + + __ li(msg, BytecodeInterpreter::method_resume); + __ b(unwind_recursive_activation); + + + //============================================================================= + // Push the last instruction out to the code buffer. + + { + __ unimplemented("end of InterpreterGenerator::generate_normal_entry", 128); + } + + interpreter_frame_manager = entry; + return interpreter_frame_manager; +} + +// Generate code for various sorts of method entries +// +address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { + address entry_point = NULL; + + switch (kind) { + case Interpreter::zerolocals : break; + case Interpreter::zerolocals_synchronized : break; + case Interpreter::native : // Fall thru + case Interpreter::native_synchronized : entry_point = ((CppInterpreterGenerator*)this)->generate_native_entry(); break; + case Interpreter::empty : break; + case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; + case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; + // These are special interpreter intrinsics which we don't support so far. + case Interpreter::java_lang_math_sin : break; + case Interpreter::java_lang_math_cos : break; + case Interpreter::java_lang_math_tan : break; + case Interpreter::java_lang_math_abs : break; + case Interpreter::java_lang_math_log : break; + case Interpreter::java_lang_math_log10 : break; + case Interpreter::java_lang_math_sqrt : break; + case Interpreter::java_lang_math_pow : break; + case Interpreter::java_lang_math_exp : break; + case Interpreter::java_lang_ref_reference_get: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; + default : ShouldNotReachHere(); break; + } + + if (entry_point) { + return entry_point; + } + return ((InterpreterGenerator*)this)->generate_normal_entry(); +} + +InterpreterGenerator::InterpreterGenerator(StubQueue* code) + : CppInterpreterGenerator(code) { + generate_all(); // down here so it can be "virtual" +} + +// How much stack a topmost interpreter method activation needs in words. +int AbstractInterpreter::size_top_interpreter_activation(Method* method) { + // Computation is in bytes not words to match layout_activation_impl + // below, but the return is in words. + + // + // 0 [TOP_IJAVA_FRAME_ABI] \ + // alignment (optional) \ | + // [operand stack / Java parameters] > stack | | + // [monitors] (optional) > monitors | | + // [PARENT_IJAVA_FRAME_ABI] \ | | + // [BytecodeInterpreter object] > interpreter \ | | | + // alignment (optional) | round | parent | round | top + // [Java result] (2 slots) > result | | | | + // [Java non-arg locals] \ locals | | | | + // [arg locals] / / / / / + // + + int locals = method->max_locals() * BytesPerWord; + int interpreter = frame::interpreter_frame_cinterpreterstate_size_in_bytes(); + int result = 2 * BytesPerWord; + + int parent = round_to(interpreter + result + locals, 16) + frame::parent_ijava_frame_abi_size; + + int stack = method->max_stack() * BytesPerWord; + int monitors = method->is_synchronized() ? frame::interpreter_frame_monitor_size_in_bytes() : 0; + int top = round_to(parent + monitors + stack, 16) + frame::top_ijava_frame_abi_size; + + return (top / BytesPerWord); +} + +void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill, + frame* caller, + frame* current, + Method* method, + intptr_t* locals, + intptr_t* stack, + intptr_t* stack_base, + intptr_t* monitor_base, + intptr_t* frame_sp, + bool is_top_frame) { + // What about any vtable? + // + to_fill->_thread = JavaThread::current(); + // This gets filled in later but make it something recognizable for now. + to_fill->_bcp = method->code_base(); + to_fill->_locals = locals; + to_fill->_constants = method->constants()->cache(); + to_fill->_method = method; + to_fill->_mdx = NULL; + to_fill->_stack = stack; + + if (is_top_frame && JavaThread::current()->popframe_forcing_deopt_reexecution()) { + to_fill->_msg = deopt_resume2; + } else { + to_fill->_msg = method_resume; + } + to_fill->_result._to_call._bcp_advance = 0; + to_fill->_result._to_call._callee_entry_point = NULL; // doesn't matter to anyone + to_fill->_result._to_call._callee = NULL; // doesn't matter to anyone + to_fill->_prev_link = NULL; + + if (caller->is_interpreted_frame()) { + interpreterState prev = caller->get_interpreterState(); + + // Support MH calls. Make sure the interpreter will return the right address: + // 1. Caller did ordinary interpreted->compiled call call: Set a prev_state + // which makes the CPP interpreter return to frame manager "return_from_interpreted_method" + // entry after finishing execution. + // 2. Caller did a MH call: If the caller has a MethodHandleInvoke in it's + // state (invariant: must be the caller of the bottom vframe) we used the + // "call_special" entry to do the call, meaning the arguments have not been + // popped from the stack. Therefore, don't enter a prev state in this case + // in order to return to "return_from_native" frame manager entry which takes + // care of popping arguments. Also, don't overwrite the MH.invoke Method in + // the prev_state in order to be able to figure out the number of arguments to + // pop. + // The parameter method can represent MethodHandle.invokeExact(...). + // The MethodHandleCompiler generates these synthetic Methods, + // including bytecodes, if an invokedynamic call gets inlined. In + // this case we want to return like from any other interpreted + // Java call, so we set _prev_link. + to_fill->_prev_link = prev; + + if (*prev->_bcp == Bytecodes::_invokeinterface || *prev->_bcp == Bytecodes::_invokedynamic) { + prev->_result._to_call._bcp_advance = 5; + } else { + prev->_result._to_call._bcp_advance = 3; + } + } + to_fill->_oop_temp = NULL; + to_fill->_stack_base = stack_base; + // Need +1 here because stack_base points to the word just above the + // first expr stack entry and stack_limit is supposed to point to + // the word just below the last expr stack entry. See + // generate_compute_interpreter_state. + to_fill->_stack_limit = stack_base - (method->max_stack() + 1); + to_fill->_monitor_base = (BasicObjectLock*) monitor_base; + + to_fill->_frame_bottom = frame_sp; + + // PPC64 specific + to_fill->_last_Java_pc = NULL; + to_fill->_last_Java_fp = NULL; + to_fill->_last_Java_sp = frame_sp; +#ifdef ASSERT + to_fill->_self_link = to_fill; + to_fill->_native_fresult = 123456.789; + to_fill->_native_lresult = CONST64(0xdeafcafedeadc0de); +#endif +} + +void BytecodeInterpreter::pd_layout_interpreterState(interpreterState istate, + address last_Java_pc, + intptr_t* last_Java_fp) { + istate->_last_Java_pc = last_Java_pc; + istate->_last_Java_fp = last_Java_fp; +} + +int AbstractInterpreter::layout_activation(Method* method, + int temps, // Number of slots on java expression stack in use. + int popframe_args, + int monitors, // Number of active monitors. + int caller_actual_parameters, + int callee_params,// Number of slots for callee parameters. + int callee_locals,// Number of slots for locals. + frame* caller, + frame* interpreter_frame, + bool is_top_frame, + bool is_bottom_frame) { + + // NOTE this code must exactly mimic what + // InterpreterGenerator::generate_compute_interpreter_state() does + // as far as allocating an interpreter frame. However there is an + // exception. With the C++ based interpreter only the top most frame + // has a full sized expression stack. The 16 byte slop factor is + // both the abi scratch area and a place to hold a result from a + // callee on its way to the callers stack. + + int monitor_size = frame::interpreter_frame_monitor_size_in_bytes() * monitors; + int frame_size; + int top_frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() + + monitor_size + + (method->max_stack() *Interpreter::stackElementWords * BytesPerWord) + + 2*BytesPerWord, + frame::alignment_in_bytes) + + frame::top_ijava_frame_abi_size; + if (is_top_frame) { + frame_size = top_frame_size; + } else { + frame_size = round_to(frame::interpreter_frame_cinterpreterstate_size_in_bytes() + + monitor_size + + ((temps - callee_params + callee_locals) * + Interpreter::stackElementWords * BytesPerWord) + + 2*BytesPerWord, + frame::alignment_in_bytes) + + frame::parent_ijava_frame_abi_size; + assert(popframe_args==0, "non-zero for top_frame only"); + } + + // If we actually have a frame to layout we must now fill in all the pieces. + if (interpreter_frame != NULL) { + + intptr_t sp = (intptr_t)interpreter_frame->sp(); + intptr_t fp = *(intptr_t *)sp; + assert(fp == (intptr_t)caller->sp(), "fp must match"); + interpreterState cur_state = + (interpreterState)(fp - frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + + // Now fill in the interpreterState object. + + intptr_t* locals; + if (caller->is_interpreted_frame()) { + // Locals must agree with the caller because it will be used to set the + // caller's tos when we return. + interpreterState prev = caller->get_interpreterState(); + // Calculate start of "locals" for MH calls. For MH calls, the + // current method() (= MH target) and prev->callee() (= + // MH.invoke*()) are different and especially have different + // signatures. To pop the argumentsof the caller, we must use + // the prev->callee()->size_of_arguments() because that's what + // the caller actually pushed. Currently, for synthetic MH + // calls (deoptimized from inlined MH calls), detected by + // is_method_handle_invoke(), we use the callee's arguments + // because here, the caller's and callee's signature match. + if (true /*!caller->is_at_mh_callsite()*/) { + locals = prev->stack() + method->size_of_parameters(); + } else { + // Normal MH call. + locals = prev->stack() + prev->callee()->size_of_parameters(); + } + } else { + bool is_deopted; + locals = (intptr_t*) (fp + ((method->max_locals() - 1) * BytesPerWord) + + frame::parent_ijava_frame_abi_size); + } + + intptr_t* monitor_base = (intptr_t*) cur_state; + intptr_t* stack_base = (intptr_t*) ((intptr_t) monitor_base - monitor_size); + + // Provide pop_frame capability on PPC64, add popframe_args. + // +1 because stack is always prepushed. + intptr_t* stack = (intptr_t*) ((intptr_t) stack_base - (temps + popframe_args + 1) * BytesPerWord); + + BytecodeInterpreter::layout_interpreterState(cur_state, + caller, + interpreter_frame, + method, + locals, + stack, + stack_base, + monitor_base, + (intptr_t*)(((intptr_t)fp)-top_frame_size), + is_top_frame); + + BytecodeInterpreter::pd_layout_interpreterState(cur_state, interpreter_return_address, + interpreter_frame->fp()); + } + return frame_size/BytesPerWord; +} + +#endif // CC_INTERP diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.hpp b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.hpp new file mode 100644 index 00000000000..af8bfb3bc55 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_CPPINTERPRETER_PPC_HPP +#define CPU_PPC_VM_CPPINTERPRETER_PPC_HPP + + protected: + + // Size of interpreter code. Increase if too small. Interpreter will + // fail with a guarantee ("not enough space for interpreter generation"); + // if too small. + // Run with +PrintInterpreter to get the VM to print out the size. + // Max size with JVMTI + + const static int InterpreterCodeSize = 12*K; + +#endif // CPU_PPC_VM_CPPINTERPRETER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp new file mode 100644 index 00000000000..dc91efc78bb --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "code/codeCache.hpp" +#include "code/nmethod.hpp" +#include "runtime/frame.hpp" +#include "runtime/init.hpp" +#include "runtime/os.hpp" +#include "utilities/debug.hpp" +#include "utilities/top.hpp" + +void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/ppc/vm/depChecker_ppc.hpp b/hotspot/src/cpu/ppc/vm/depChecker_ppc.hpp new file mode 100644 index 00000000000..33f04c06050 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/depChecker_ppc.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_DEPCHECKER_PPC_HPP +#define CPU_PPC_VM_DEPCHECKER_PPC_HPP + +// Nothing to do on ppc64 + +#endif // CPU_PPC_VM_DEPCHECKER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/disassembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/disassembler_ppc.hpp new file mode 100644 index 00000000000..eb2a81d390e --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/disassembler_ppc.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_DISASSEMBLER_PPC_HPP +#define CPU_PPC_VM_DISASSEMBLER_PPC_HPP + + static int pd_instruction_alignment() { + return sizeof(int); + } + + static const char* pd_cpu_opts() { + return "ppc64"; + } + +#endif // CPU_PPC_VM_DISASSEMBLER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp new file mode 100644 index 00000000000..03d525db4e3 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "oops/markOop.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/monitorChunk.hpp" +#include "runtime/signature.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/stubRoutines.hpp" +#include "vmreg_ppc.inline.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#include "runtime/vframeArray.hpp" +#endif + +#ifndef CC_INTERP +#error "CC_INTERP must be defined on PPC64" +#endif + +#ifdef ASSERT +void RegisterMap::check_location_valid() { +} +#endif // ASSERT + +bool frame::safe_for_sender(JavaThread *thread) { + bool safe = false; + address cursp = (address)sp(); + address curfp = (address)fp(); + if ((cursp != NULL && curfp != NULL && + (cursp <= thread->stack_base() && cursp >= thread->stack_base() - thread->stack_size())) && + (curfp <= thread->stack_base() && curfp >= thread->stack_base() - thread->stack_size())) { + safe = true; + } + return safe; +} + +bool frame::is_interpreted_frame() const { + return Interpreter::contains(pc()); +} + +frame frame::sender_for_entry_frame(RegisterMap *map) const { + assert(map != NULL, "map must be set"); + // Java frame called from C; skip all C frames and return top C + // frame of that chunk as the sender. + JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor(); + assert(!entry_frame_is_first(), "next Java fp must be non zero"); + assert(jfa->last_Java_sp() > _sp, "must be above this frame on stack"); + map->clear(); + assert(map->include_argument_oops(), "should be set by clear"); + + if (jfa->last_Java_pc() != NULL) { + frame fr(jfa->last_Java_sp(), jfa->last_Java_pc()); + return fr; + } + // Last_java_pc is not set, if we come here from compiled code. The + // constructor retrieves the PC from the stack. + frame fr(jfa->last_Java_sp()); + return fr; +} + +frame frame::sender_for_interpreter_frame(RegisterMap *map) const { + // Pass callers initial_caller_sp as unextended_sp. + return frame(sender_sp(), sender_pc(), (intptr_t*)((parent_ijava_frame_abi *)callers_abi())->initial_caller_sp); +} + +frame frame::sender_for_compiled_frame(RegisterMap *map) const { + assert(map != NULL, "map must be set"); + + // Frame owned by compiler. + address pc = *compiled_sender_pc_addr(_cb); + frame caller(compiled_sender_sp(_cb), pc); + + // Now adjust the map. + + // Get the rest. + if (map->update_map()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread())); + if (_cb->oop_maps() != NULL) { + OopMapSet::update_register_map(this, map); + } + } + + return caller; +} + +intptr_t* frame::compiled_sender_sp(CodeBlob* cb) const { + return sender_sp(); +} + +address* frame::compiled_sender_pc_addr(CodeBlob* cb) const { + return sender_pc_addr(); +} + +frame frame::sender(RegisterMap* map) const { + // Default is we do have to follow them. The sender_for_xxx will + // update it accordingly. + map->set_include_argument_oops(false); + + if (is_entry_frame()) return sender_for_entry_frame(map); + if (is_interpreted_frame()) return sender_for_interpreter_frame(map); + assert(_cb == CodeCache::find_blob(pc()),"Must be the same"); + + if (_cb != NULL) { + return sender_for_compiled_frame(map); + } + // Must be native-compiled frame, i.e. the marshaling code for native + // methods that exists in the core system. + return frame(sender_sp(), sender_pc()); +} + +void frame::patch_pc(Thread* thread, address pc) { + if (TracePcPatching) { + tty->print_cr("patch_pc at address " PTR_FORMAT " [" PTR_FORMAT " -> " PTR_FORMAT "]", + &((address*) _sp)[-1], ((address*) _sp)[-1], pc); + } + own_abi()->lr = (uint64_t)pc; + _cb = CodeCache::find_blob(pc); + if (_cb != NULL && _cb->is_nmethod() && ((nmethod*)_cb)->is_deopt_pc(_pc)) { + address orig = (((nmethod*)_cb)->get_original_pc(this)); + assert(orig == _pc, "expected original to be stored before patching"); + _deopt_state = is_deoptimized; + // Leave _pc as is. + } else { + _deopt_state = not_deoptimized; + _pc = pc; + } +} + +void frame::pd_gc_epilog() { + if (is_interpreted_frame()) { + // Set constant pool cache entry for interpreter. + Method* m = interpreter_frame_method(); + + *interpreter_frame_cpoolcache_addr() = m->constants()->cache(); + } +} + +bool frame::is_interpreted_frame_valid(JavaThread* thread) const { + // Is there anything to do? + assert(is_interpreted_frame(), "Not an interpreted frame"); + return true; +} + +BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) { + assert(is_interpreted_frame(), "interpreted frame expected"); + Method* method = interpreter_frame_method(); + BasicType type = method->result_type(); + +#ifdef CC_INTERP + if (method->is_native()) { + // Prior to calling into the runtime to notify the method exit the possible + // result value is saved into the interpreter frame. + interpreterState istate = get_interpreterState(); + address lresult = (address)istate + in_bytes(BytecodeInterpreter::native_lresult_offset()); + address fresult = (address)istate + in_bytes(BytecodeInterpreter::native_fresult_offset()); + + switch (method->result_type()) { + case T_OBJECT: + case T_ARRAY: { + oop* obj_p = *(oop**)lresult; + oop obj = (obj_p == NULL) ? NULL : *obj_p; + assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + *oop_result = obj; + break; + } + // We use std/stfd to store the values. + case T_BOOLEAN : value_result->z = (jboolean) *(unsigned long*)lresult; break; + case T_INT : value_result->i = (jint) *(long*)lresult; break; + case T_CHAR : value_result->c = (jchar) *(unsigned long*)lresult; break; + case T_SHORT : value_result->s = (jshort) *(long*)lresult; break; + case T_BYTE : value_result->z = (jbyte) *(long*)lresult; break; + case T_LONG : value_result->j = (jlong) *(long*)lresult; break; + case T_FLOAT : value_result->f = (jfloat) *(double*)fresult; break; + case T_DOUBLE : value_result->d = (jdouble) *(double*)fresult; break; + case T_VOID : /* Nothing to do */ break; + default : ShouldNotReachHere(); + } + } else { + intptr_t* tos_addr = interpreter_frame_tos_address(); + switch (method->result_type()) { + case T_OBJECT: + case T_ARRAY: { + oop obj = *(oop*)tos_addr; + assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + *oop_result = obj; + } + case T_BOOLEAN : value_result->z = (jboolean) *(jint*)tos_addr; break; + case T_BYTE : value_result->b = (jbyte) *(jint*)tos_addr; break; + case T_CHAR : value_result->c = (jchar) *(jint*)tos_addr; break; + case T_SHORT : value_result->s = (jshort) *(jint*)tos_addr; break; + case T_INT : value_result->i = *(jint*)tos_addr; break; + case T_LONG : value_result->j = *(jlong*)tos_addr; break; + case T_FLOAT : value_result->f = *(jfloat*)tos_addr; break; + case T_DOUBLE : value_result->d = *(jdouble*)tos_addr; break; + case T_VOID : /* Nothing to do */ break; + default : ShouldNotReachHere(); + } + } +#else + Unimplemented(); +#endif + return type; +} + +#ifndef PRODUCT + +void frame::describe_pd(FrameValues& values, int frame_no) { + if (is_interpreted_frame()) { +#ifdef CC_INTERP + interpreterState istate = get_interpreterState(); + values.describe(frame_no, (intptr_t*)istate, "istate"); + values.describe(frame_no, (intptr_t*)&(istate->_thread), " thread"); + values.describe(frame_no, (intptr_t*)&(istate->_bcp), " bcp"); + values.describe(frame_no, (intptr_t*)&(istate->_locals), " locals"); + values.describe(frame_no, (intptr_t*)&(istate->_constants), " constants"); + values.describe(frame_no, (intptr_t*)&(istate->_method), err_msg(" method = %s", istate->_method->name_and_sig_as_C_string())); + values.describe(frame_no, (intptr_t*)&(istate->_mdx), " mdx"); + values.describe(frame_no, (intptr_t*)&(istate->_stack), " stack"); + values.describe(frame_no, (intptr_t*)&(istate->_msg), err_msg(" msg = %s", BytecodeInterpreter::C_msg(istate->_msg))); + values.describe(frame_no, (intptr_t*)&(istate->_result), " result"); + values.describe(frame_no, (intptr_t*)&(istate->_prev_link), " prev_link"); + values.describe(frame_no, (intptr_t*)&(istate->_oop_temp), " oop_temp"); + values.describe(frame_no, (intptr_t*)&(istate->_stack_base), " stack_base"); + values.describe(frame_no, (intptr_t*)&(istate->_stack_limit), " stack_limit"); + values.describe(frame_no, (intptr_t*)&(istate->_monitor_base), " monitor_base"); + values.describe(frame_no, (intptr_t*)&(istate->_frame_bottom), " frame_bottom"); + values.describe(frame_no, (intptr_t*)&(istate->_last_Java_pc), " last_Java_pc"); + values.describe(frame_no, (intptr_t*)&(istate->_last_Java_fp), " last_Java_fp"); + values.describe(frame_no, (intptr_t*)&(istate->_last_Java_sp), " last_Java_sp"); + values.describe(frame_no, (intptr_t*)&(istate->_self_link), " self_link"); + values.describe(frame_no, (intptr_t*)&(istate->_native_fresult), " native_fresult"); + values.describe(frame_no, (intptr_t*)&(istate->_native_lresult), " native_lresult"); +#else + Unimplemented(); +#endif + } +} +#endif + +void frame::adjust_unextended_sp() { + // If we are returning to a compiled MethodHandle call site, the + // saved_fp will in fact be a saved value of the unextended SP. The + // simplest way to tell whether we are returning to such a call site + // is as follows: + + if (is_compiled_frame() && false /*is_at_mh_callsite()*/) { // TODO PPC port + // If the sender PC is a deoptimization point, get the original + // PC. For MethodHandle call site the unextended_sp is stored in + // saved_fp. + _unextended_sp = _fp - _cb->frame_size(); + +#ifdef ASSERT + nmethod *sender_nm = _cb->as_nmethod_or_null(); + assert(sender_nm && *_sp == *_unextended_sp, "backlink changed"); + + intptr_t* sp = _unextended_sp; // check if stack can be walked from here + for (int x = 0; x < 5; ++x) { // check up to a couple of backlinks + intptr_t* prev_sp = *(intptr_t**)sp; + if (prev_sp == 0) break; // end of stack + assert(prev_sp>sp, "broken stack"); + sp = prev_sp; + } + + if (sender_nm->is_deopt_mh_entry(_pc)) { // checks for deoptimization + address original_pc = sender_nm->get_original_pc(this); + assert(sender_nm->insts_contains(original_pc), "original PC must be in nmethod"); + assert(sender_nm->is_method_handle_return(original_pc), "must be"); + } +#endif + } +} + +intptr_t *frame::initial_deoptimization_info() { + // unused... but returns fp() to minimize changes introduced by 7087445 + return fp(); +} diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp new file mode 100644 index 00000000000..73c216e4c82 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_FRAME_PPC_HPP +#define CPU_PPC_VM_FRAME_PPC_HPP + +#include "runtime/synchronizer.hpp" +#include "utilities/top.hpp" + +#ifndef CC_INTERP +#error "CC_INTERP must be defined on PPC64" +#endif + + // C frame layout on PPC-64. + // + // In this figure the stack grows upwards, while memory grows + // downwards. See "64-bit PowerPC ELF ABI Supplement Version 1.7", + // IBM Corp. (2003-10-29) + // (http://math-atlas.sourceforge.net/devel/assembly/PPC-elf64abi-1.7.pdf). + // + // Square brackets denote stack regions possibly larger + // than a single 64 bit slot. + // + // STACK: + // 0 [C_FRAME] <-- SP after prolog (mod 16 = 0) + // [C_FRAME] <-- SP before prolog + // ... + // [C_FRAME] + // + // C_FRAME: + // 0 [ABI_112] + // 112 CARG_9: outgoing arg 9 (arg_1 ... arg_8 via gpr_3 ... gpr_{10}) + // ... + // 40+M*8 CARG_M: outgoing arg M (M is the maximum of outgoing args taken over all call sites in the procedure) + // local 1 + // ... + // local N + // spill slot for vector reg (16 bytes aligned) + // ... + // spill slot for vector reg + // alignment (4 or 12 bytes) + // V SR_VRSAVE + // V+4 spill slot for GR + // ... ... + // spill slot for GR + // spill slot for FR + // ... + // spill slot for FR + // + // ABI_48: + // 0 caller's SP + // 8 space for condition register (CR) for next call + // 16 space for link register (LR) for next call + // 24 reserved + // 32 reserved + // 40 space for TOC (=R2) register for next call + // + // ABI_112: + // 0 [ABI_48] + // 48 CARG_1: spill slot for outgoing arg 1. used by next callee. + // ... ... + // 104 CARG_8: spill slot for outgoing arg 8. used by next callee. + // + + public: + + // C frame layout + + enum { + // stack alignment + alignment_in_bytes = 16, + // log_2(16*8 bits) = 7. + log_2_of_alignment_in_bits = 7 + }; + + // ABI_48: + struct abi_48 { + uint64_t callers_sp; + uint64_t cr; //_16 + uint64_t lr; + uint64_t reserved1; //_16 + uint64_t reserved2; + uint64_t toc; //_16 + // nothing to add here! + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + abi_48_size = sizeof(abi_48) + }; + + struct abi_112 : abi_48 { + uint64_t carg_1; + uint64_t carg_2; //_16 + uint64_t carg_3; + uint64_t carg_4; //_16 + uint64_t carg_5; + uint64_t carg_6; //_16 + uint64_t carg_7; + uint64_t carg_8; //_16 + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + abi_112_size = sizeof(abi_112) + }; + + #define _abi(_component) \ + (offset_of(frame::abi_112, _component)) + + struct abi_112_spill : abi_112 { + // additional spill slots + uint64_t spill_ret; + uint64_t spill_fret; //_16 + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + abi_112_spill_size = sizeof(abi_112_spill) + }; + + #define _abi_112_spill(_component) \ + (offset_of(frame::abi_112_spill, _component)) + + // non-volatile GPRs: + + struct spill_nonvolatiles { + uint64_t r14; + uint64_t r15; //_16 + uint64_t r16; + uint64_t r17; //_16 + uint64_t r18; + uint64_t r19; //_16 + uint64_t r20; + uint64_t r21; //_16 + uint64_t r22; + uint64_t r23; //_16 + uint64_t r24; + uint64_t r25; //_16 + uint64_t r26; + uint64_t r27; //_16 + uint64_t r28; + uint64_t r29; //_16 + uint64_t r30; + uint64_t r31; //_16 + + double f14; + double f15; + double f16; + double f17; + double f18; + double f19; + double f20; + double f21; + double f22; + double f23; + double f24; + double f25; + double f26; + double f27; + double f28; + double f29; + double f30; + double f31; + + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + spill_nonvolatiles_size = sizeof(spill_nonvolatiles) + }; + + #define _spill_nonvolatiles_neg(_component) \ + (int)(-frame::spill_nonvolatiles_size + offset_of(frame::spill_nonvolatiles, _component)) + + // Frame layout for the Java interpreter on PPC64. + // + // This frame layout provides a C-like frame for every Java frame. + // + // In these figures the stack grows upwards, while memory grows + // downwards. Square brackets denote regions possibly larger than + // single 64 bit slots. + // + // STACK (no JNI, no compiled code, no library calls, + // interpreter-loop is active): + // 0 [InterpretMethod] + // [TOP_IJAVA_FRAME] + // [PARENT_IJAVA_FRAME] + // ... + // [PARENT_IJAVA_FRAME] + // [ENTRY_FRAME] + // [C_FRAME] + // ... + // [C_FRAME] + // + // TOP_IJAVA_FRAME: + // 0 [TOP_IJAVA_FRAME_ABI] + // alignment (optional) + // [operand stack] + // [monitors] (optional) + // [cInterpreter object] + // result, locals, and arguments are in parent frame! + // + // PARENT_IJAVA_FRAME: + // 0 [PARENT_IJAVA_FRAME_ABI] + // alignment (optional) + // [callee's Java result] + // [callee's locals w/o arguments] + // [outgoing arguments] + // [used part of operand stack w/o arguments] + // [monitors] (optional) + // [cInterpreter object] + // + // ENTRY_FRAME: + // 0 [PARENT_IJAVA_FRAME_ABI] + // alignment (optional) + // [callee's Java result] + // [callee's locals w/o arguments] + // [outgoing arguments] + // [ENTRY_FRAME_LOCALS] + // + // PARENT_IJAVA_FRAME_ABI: + // 0 [ABI_48] + // top_frame_sp + // initial_caller_sp + // + // TOP_IJAVA_FRAME_ABI: + // 0 [PARENT_IJAVA_FRAME_ABI] + // carg_3_unused + // carg_4_unused + // carg_5_unused + // carg_6_unused + // carg_7_unused + // frame_manager_lr + // + + // PARENT_IJAVA_FRAME_ABI + + struct parent_ijava_frame_abi : abi_48 { + // SOE registers. + // C2i adapters spill their top-frame stack-pointer here. + uint64_t top_frame_sp; // carg_1 + // Sp of calling compiled frame before it was resized by the c2i + // adapter or sp of call stub. Does not contain a valid value for + // non-initial frames. + uint64_t initial_caller_sp; // carg_2 + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + parent_ijava_frame_abi_size = sizeof(parent_ijava_frame_abi) + }; + + #define _parent_ijava_frame_abi(_component) \ + (offset_of(frame::parent_ijava_frame_abi, _component)) + + // TOP_IJAVA_FRAME_ABI + + struct top_ijava_frame_abi : parent_ijava_frame_abi { + uint64_t carg_3_unused; // carg_3 + uint64_t card_4_unused; //_16 carg_4 + uint64_t carg_5_unused; // carg_5 + uint64_t carg_6_unused; //_16 carg_6 + uint64_t carg_7_unused; // carg_7 + // Use arg8 for storing frame_manager_lr. The size of + // top_ijava_frame_abi must match abi_112. + uint64_t frame_manager_lr; //_16 carg_8 + // nothing to add here! + // aligned to frame::alignment_in_bytes (16) + }; + + enum { + top_ijava_frame_abi_size = sizeof(top_ijava_frame_abi) + }; + + #define _top_ijava_frame_abi(_component) \ + (offset_of(frame::top_ijava_frame_abi, _component)) + + // ENTRY_FRAME + + struct entry_frame_locals { + uint64_t call_wrapper_address; + uint64_t result_address; //_16 + uint64_t result_type; + uint64_t arguments_tos_address; //_16 + // aligned to frame::alignment_in_bytes (16) + uint64_t r[spill_nonvolatiles_size/sizeof(uint64_t)]; + }; + + enum { + entry_frame_locals_size = sizeof(entry_frame_locals) + }; + + #define _entry_frame_locals_neg(_component) \ + (int)(-frame::entry_frame_locals_size + offset_of(frame::entry_frame_locals, _component)) + + + // Frame layout for JIT generated methods + // + // In these figures the stack grows upwards, while memory grows + // downwards. Square brackets denote regions possibly larger than single + // 64 bit slots. + // + // STACK (interpreted Java calls JIT generated Java): + // [JIT_FRAME] <-- SP (mod 16 = 0) + // [TOP_IJAVA_FRAME] + // ... + // + // JIT_FRAME (is a C frame according to PPC-64 ABI): + // [out_preserve] + // [out_args] + // [spills] + // [pad_1] + // [monitor] (optional) + // ... + // [monitor] (optional) + // [pad_2] + // [in_preserve] added / removed by prolog / epilog + // + + // JIT_ABI (TOP and PARENT) + + struct jit_abi { + uint64_t callers_sp; + uint64_t cr; + uint64_t lr; + uint64_t toc; + // Nothing to add here! + // NOT ALIGNED to frame::alignment_in_bytes (16). + }; + + struct jit_out_preserve : jit_abi { + // Nothing to add here! + }; + + struct jit_in_preserve { + // Nothing to add here! + }; + + enum { + jit_out_preserve_size = sizeof(jit_out_preserve), + jit_in_preserve_size = sizeof(jit_in_preserve) + }; + + struct jit_monitor { + uint64_t monitor[1]; + }; + + enum { + jit_monitor_size = sizeof(jit_monitor), + }; + + private: + + // STACK: + // ... + // [THIS_FRAME] <-- this._sp (stack pointer for this frame) + // [CALLER_FRAME] <-- this.fp() (_sp of caller's frame) + // ... + // + + // frame pointer for this frame + intptr_t* _fp; + + // The frame's stack pointer before it has been extended by a c2i adapter; + // needed by deoptimization + intptr_t* _unextended_sp; + void adjust_unextended_sp(); + + public: + + // Accessors for fields + intptr_t* fp() const { return _fp; } + + // Accessors for ABIs + inline abi_48* own_abi() const { return (abi_48*) _sp; } + inline abi_48* callers_abi() const { return (abi_48*) _fp; } + + private: + + // Find codeblob and set deopt_state. + inline void find_codeblob_and_set_pc_and_deopt_state(address pc); + + public: + + // Constructors + inline frame(intptr_t* sp); + frame(intptr_t* sp, address pc); + inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp); + + private: + + intptr_t* compiled_sender_sp(CodeBlob* cb) const; + address* compiled_sender_pc_addr(CodeBlob* cb) const; + address* sender_pc_addr(void) const; + + public: + +#ifdef CC_INTERP + // Additional interface for interpreter frames: + inline interpreterState get_interpreterState() const; +#endif + + // Size of a monitor in bytes. + static int interpreter_frame_monitor_size_in_bytes(); + + // The size of a cInterpreter object. + static inline int interpreter_frame_cinterpreterstate_size_in_bytes(); + + private: + + // PPC port: permgen stuff + ConstantPoolCache** interpreter_frame_cpoolcache_addr() const; + + public: + + // Additional interface for entry frames: + inline entry_frame_locals* get_entry_frame_locals() const { + return (entry_frame_locals*) (((address) fp()) - entry_frame_locals_size); + } + + enum { + // normal return address is 1 bundle past PC + pc_return_offset = 0 + }; + +#endif // CPU_PPC_VM_FRAME_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp new file mode 100644 index 00000000000..bb908225155 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_FRAME_PPC_INLINE_HPP +#define CPU_PPC_VM_FRAME_PPC_INLINE_HPP + +#ifndef CC_INTERP +#error "CC_INTERP must be defined on PPC64" +#endif + +// Inline functions for ppc64 frames: + +// Find codeblob and set deopt_state. +inline void frame::find_codeblob_and_set_pc_and_deopt_state(address pc) { + assert(pc != NULL, "precondition: must have PC"); + + _cb = CodeCache::find_blob(pc); + _pc = pc; // Must be set for get_deopt_original_pc() + + _fp = (intptr_t*)own_abi()->callers_sp; + // Use _fp - frame_size, needs to be done between _cb and _pc initialization + // and get_deopt_original_pc. + adjust_unextended_sp(); + + address original_pc = nmethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + _pc = original_pc; + _deopt_state = is_deoptimized; + } else { + _deopt_state = not_deoptimized; + } + + assert(((uint64_t)_sp & 0xf) == 0, "SP must be 16-byte aligned"); +} + +// Constructors + +// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state. +inline frame::frame() : _sp(NULL), _unextended_sp(NULL), _fp(NULL), _cb(NULL), _pc(NULL), _deopt_state(unknown) {} + +inline frame::frame(intptr_t* sp) : _sp(sp), _unextended_sp(sp) { + find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->lr); // also sets _fp and adjusts _unextended_sp +} + +inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _unextended_sp(sp) { + find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp +} + +inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _unextended_sp(unextended_sp) { + find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp +} + +// Accessors + +// Return unique id for this frame. The id must have a value where we +// can distinguish identity and younger/older relationship. NULL +// represents an invalid (incomparable) frame. +inline intptr_t* frame::id(void) const { + // Use the _unextended_pc as the frame's ID. Because we have no + // adapters, but resized compiled frames, some of the new code + // (e.g. JVMTI) wouldn't work if we return the (current) SP of the + // frame. + return _unextended_sp; +} + +// Return true if this frame is older (less recent activation) than +// the frame represented by id. +inline bool frame::is_older(intptr_t* id) const { + assert(this->id() != NULL && id != NULL, "NULL frame id"); + // Stack grows towards smaller addresses on ppc64. + return this->id() > id; +} + +inline int frame::frame_size(RegisterMap* map) const { + // Stack grows towards smaller addresses on PPC64: sender is at a higher address. + return sender_sp() - sp(); +} + +// Return the frame's stack pointer before it has been extended by a +// c2i adapter. This is needed by deoptimization for ignoring c2i adapter +// frames. +inline intptr_t* frame::unextended_sp() const { + return _unextended_sp; +} + +// All frames have this field. +inline address frame::sender_pc() const { + return (address)callers_abi()->lr; +} +inline address* frame::sender_pc_addr() const { + return (address*)&(callers_abi()->lr); +} + +// All frames have this field. +inline intptr_t* frame::sender_sp() const { + return (intptr_t*)callers_abi(); +} + +// All frames have this field. +inline intptr_t* frame::link() const { + return (intptr_t*)callers_abi()->callers_sp; +} + +inline intptr_t* frame::real_fp() const { + return fp(); +} + +#ifdef CC_INTERP + +inline interpreterState frame::get_interpreterState() const { + return (interpreterState)(((address)callers_abi()) + - frame::interpreter_frame_cinterpreterstate_size_in_bytes()); +} + +inline intptr_t** frame::interpreter_frame_locals_addr() const { + interpreterState istate = get_interpreterState(); + return (intptr_t**)&istate->_locals; +} + +inline intptr_t* frame::interpreter_frame_bcx_addr() const { + interpreterState istate = get_interpreterState(); + return (intptr_t*)&istate->_bcp; +} + +inline intptr_t* frame::interpreter_frame_mdx_addr() const { + interpreterState istate = get_interpreterState(); + return (intptr_t*)&istate->_mdx; +} + +inline intptr_t* frame::interpreter_frame_expression_stack() const { + return (intptr_t*)interpreter_frame_monitor_end() - 1; +} + +inline jint frame::interpreter_frame_expression_stack_direction() { + return -1; +} + +// top of expression stack +inline intptr_t* frame::interpreter_frame_tos_address() const { + interpreterState istate = get_interpreterState(); + return istate->_stack + 1; +} + +inline intptr_t* frame::interpreter_frame_tos_at(jint offset) const { + return &interpreter_frame_tos_address()[offset]; +} + +// monitor elements + +// in keeping with Intel side: end is lower in memory than begin; +// and beginning element is oldest element +// Also begin is one past last monitor. + +inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { + return get_interpreterState()->monitor_base(); +} + +inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { + return (BasicObjectLock*)get_interpreterState()->stack_base(); +} + +inline int frame::interpreter_frame_cinterpreterstate_size_in_bytes() { + // Size of an interpreter object. Not aligned with frame size. + return round_to(sizeof(BytecodeInterpreter), 8); +} + +inline Method** frame::interpreter_frame_method_addr() const { + interpreterState istate = get_interpreterState(); + return &istate->_method; +} + +// Constant pool cache + +inline ConstantPoolCache** frame::interpreter_frame_cpoolcache_addr() const { + interpreterState istate = get_interpreterState(); + return &istate->_constants; // should really use accessor +} + +inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const { + interpreterState istate = get_interpreterState(); + return &istate->_constants; +} +#endif // CC_INTERP + +inline int frame::interpreter_frame_monitor_size() { + // Number of stack slots for a monitor. + return round_to(BasicObjectLock::size(), // number of stack slots + WordsPerLong); // number of stack slots for a Java long +} + +inline int frame::interpreter_frame_monitor_size_in_bytes() { + return frame::interpreter_frame_monitor_size() * wordSize; +} + +// entry frames + +inline intptr_t* frame::entry_frame_argument_at(int offset) const { + // Since an entry frame always calls the interpreter first, the + // parameters are on the stack and relative to known register in the + // entry frame. + intptr_t* tos = (intptr_t*)get_entry_frame_locals()->arguments_tos_address; + return &tos[offset + 1]; // prepushed tos +} + +inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const { + return (JavaCallWrapper**)&get_entry_frame_locals()->call_wrapper_address; +} + +inline oop frame::saved_oop_result(RegisterMap* map) const { + return *((oop*)map->location(R3->as_VMReg())); +} + +inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { + *((oop*)map->location(R3->as_VMReg())) = obj; +} + +#endif // CPU_PPC_VM_FRAME_PPC_INLINE_HPP diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp new file mode 100644 index 00000000000..889d2857bb2 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP +#define CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP + +// Size of PPC Instructions +const int BytesPerInstWord = 4; + +const int StackAlignmentInBytes = 16; + +#endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp new file mode 100644 index 00000000000..dfbe511ea03 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_GLOBALS_PPC_HPP +#define CPU_PPC_VM_GLOBALS_PPC_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + +define_pd_global(bool, ConvertSleepToYield, true); +define_pd_global(bool, ShareVtableStubs, false); // Improves performance markedly for mtrt and compress. +define_pd_global(bool, NeedsDeoptSuspend, false); // Only register window machines need this. + + +define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks. +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast. + +// Use large code-entry alignment. +define_pd_global(intx, CodeEntryAlignment, 128); +define_pd_global(intx, OptoLoopAlignment, 16); +define_pd_global(intx, InlineFrequencyCount, 100); +define_pd_global(intx, InlineSmallCode, 1500); + +define_pd_global(intx, PreInflateSpin, 10); + +// Flags for template interpreter. +define_pd_global(bool, RewriteBytecodes, true); +define_pd_global(bool, RewriteFrequentPairs, true); + +define_pd_global(bool, UseMembar, false); + +// GC Ergo Flags +define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // Default max size of CMS young gen, per GC worker thread. + + +// Platform dependent flag handling: flags only defined on this platform. +#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ + product(uintx, PowerArchitecturePPC64, 0, \ + "CPU Version: x for PowerX. Currently recognizes Power5 to " \ + "Power7. Default is 0. CPUs newer than Power7 will be " \ + "recognized as Power7.") \ + \ + /* Reoptimize code-sequences of calls at runtime, e.g. replace an */ \ + /* indirect call by a direct call. */ \ + product(bool, ReoptimizeCallSequences, true, \ + "Reoptimize code-sequences of calls at runtime.") \ + \ + product(bool, UseLoadInstructionsForStackBangingPPC64, false, \ + "Use load instructions for stack banging.") \ + \ + /* special instructions */ \ + \ + product(bool, UseCountLeadingZerosInstructionsPPC64, true, \ + "Use count leading zeros instructions.") \ + \ + product(bool, UseExtendedLoadAndReserveInstructionsPPC64, false, \ + "Use extended versions of load-and-reserve instructions.") \ + \ + product(bool, UseRotateAndMaskInstructionsPPC64, true, \ + "Use rotate and mask instructions.") \ + \ + product(bool, UseStaticBranchPredictionInCompareAndSwapPPC64, true, \ + "Use static branch prediction hints in CAS operations.") \ + \ + /* Trap based checks. */ \ + /* Trap based checks use the ppc trap instructions to check certain */ \ + /* conditions. This instruction raises a SIGTRAP caught by the */ \ + /* exception handler of the VM. */ \ + product(bool, UseSIGTRAP, false, \ + "Allow trap instructions that make use of SIGTRAP. Use this to " \ + "switch off all optimizations requiring SIGTRAP.") \ + product(bool, TrapBasedICMissChecks, true, \ + "Raise and handle SIGTRAP if inline cache miss detected.") \ + product(bool, TrapBasedNotEntrantChecks, true, \ + "Raise and handle SIGTRAP if calling not entrant or zombie" \ + " method.") \ + product(bool, TrapBasedNullChecks, true, \ + "Generate code for null checks that uses a cmp and trap " \ + "instruction raising SIGTRAP. This is only used if an access to" \ + "null (+offset) will not raise a SIGSEGV.") \ + product(bool, TrapBasedRangeChecks, true, \ + "Raise and handle SIGTRAP if array out of bounds check fails.") \ + product(bool, TraceTraps, false, "Trace all traps the signal handler" \ + "handles.") \ + \ + product(bool, ZapMemory, false, "Write 0x0101... to empty memory." \ + " Use this to ease debugging.") \ + + + +#endif // CPU_PPC_VM_GLOBALS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/icBuffer_ppc.cpp b/hotspot/src/cpu/ppc/vm/icBuffer_ppc.cpp new file mode 100644 index 00000000000..e991efb7645 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/icBuffer_ppc.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "assembler_ppc.inline.hpp" +#include "code/icBuffer.hpp" +#include "gc_interface/collectedHeap.inline.hpp" +#include "interpreter/bytecodes.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_ppc.hpp" +#include "oops/oop.inline.hpp" +#include "oops/oop.inline2.hpp" + +#define __ masm. + +int InlineCacheBuffer::ic_stub_code_size() { + return MacroAssembler::load_const_size + MacroAssembler::b64_patchable_size; +} + +void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { + ResourceMark rm; + CodeBuffer code(code_begin, ic_stub_code_size()); + MacroAssembler masm(&code); + // Note: even though the code contains an embedded metadata, we do not need reloc info + // because + // (1) the metadata is old (i.e., doesn't matter for scavenges) + // (2) these ICStubs are removed *before* a GC happens, so the roots disappear. + + // Load the oop ... + __ load_const(R19_method, (address) cached_value, R0); + // ... and jump to entry point. + __ b64_patchable((address) entry_point, relocInfo::none); + + __ flush(); +} + +address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { + NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object + NativeJump* jump = nativeJump_at(move->next_instruction_address()); + return jump->jump_destination(); +} + +void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { + NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object + void* o = (void*)move->data(); + return o; +} + diff --git a/hotspot/src/cpu/ppc/vm/icache_ppc.cpp b/hotspot/src/cpu/ppc/vm/icache_ppc.cpp new file mode 100644 index 00000000000..386e00dbd9f --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/icache_ppc.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "assembler_ppc.inline.hpp" +#include "runtime/icache.hpp" + +// Use inline assembler to implement icache flush. +int ppc64_flush_icache(address start, int lines, int magic){ + address end = start + (unsigned int)lines*ICache::line_size; + assert(start <= end, "flush_icache parms"); + + // store modified cache lines from data cache + for (address a=start; amark().set_unlocked(); + // monitor->lock()->set_displaced_header(displaced_header); + // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) { + // // We stored the monitor address into the object's mark word. + // } else if (THREAD->is_lock_owned((address)displaced_header)) + // // Simple recursive case. + // monitor->lock()->set_displaced_header(NULL); + // } else { + // // Slow path. + // InterpreterRuntime::monitorenter(THREAD, monitor); + // } + + const Register displaced_header = R7_ARG5; + const Register object_mark_addr = R8_ARG6; + const Register current_header = R9_ARG7; + const Register tmp = R10_ARG8; + + Label done; + Label slow_case; + + assert_different_registers(displaced_header, object_mark_addr, current_header, tmp); + + + // markOop displaced_header = obj->mark().set_unlocked(); + + // Load markOop from object into displaced_header. + ld(displaced_header, oopDesc::mark_offset_in_bytes(), object); + + if (UseBiasedLocking) { + biased_locking_enter(CCR0, object, displaced_header, tmp, current_header, done, &slow_case); + } + + // Set displaced_header to be (markOop of object | UNLOCK_VALUE). + ori(displaced_header, displaced_header, markOopDesc::unlocked_value); + + + // monitor->lock()->set_displaced_header(displaced_header); + + // Initialize the box (Must happen before we update the object mark!). + std(displaced_header, BasicObjectLock::lock_offset_in_bytes() + + BasicLock::displaced_header_offset_in_bytes(), monitor); + + // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) { + + // Store stack address of the BasicObjectLock (this is monitor) into object. + addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes()); + + // Must fence, otherwise, preceding store(s) may float below cmpxchg. + // CmpxchgX sets CCR0 to cmpX(current, displaced). + fence(); // TODO: replace by MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq ? + cmpxchgd(/*flag=*/CCR0, + /*current_value=*/current_header, + /*compare_value=*/displaced_header, /*exchange_value=*/monitor, + /*where=*/object_mark_addr, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock()); + + // If the compare-and-exchange succeeded, then we found an unlocked + // object and we have now locked it. + beq(CCR0, done); + + + // } else if (THREAD->is_lock_owned((address)displaced_header)) + // // Simple recursive case. + // monitor->lock()->set_displaced_header(NULL); + + // We did not see an unlocked object so try the fast recursive case. + + // Check if owner is self by comparing the value in the markOop of object + // (current_header) with the stack pointer. + sub(current_header, current_header, R1_SP); + + assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); + load_const_optimized(tmp, + (address) (~(os::vm_page_size()-1) | + markOopDesc::lock_mask_in_place)); + + and_(R0/*==0?*/, current_header, tmp); + // If condition is true we are done and hence we can store 0 in the displaced + // header indicating it is a recursive lock. + bne(CCR0, slow_case); + release(); + std(R0/*==0!*/, BasicObjectLock::lock_offset_in_bytes() + + BasicLock::displaced_header_offset_in_bytes(), monitor); + b(done); + + + // } else { + // // Slow path. + // InterpreterRuntime::monitorenter(THREAD, monitor); + + // None of the above fast optimizations worked so we have to get into the + // slow case of monitor enter. + bind(slow_case); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), + monitor, /*check_for_exceptions=*/false); + // } + + bind(done); + } +} + +// Unlocks an object. Used in monitorexit bytecode and remove_activation. +// +// Registers alive +// monitor - Address of the BasicObjectLock to be used for locking, +// which must be initialized with the object to lock. +// +// Throw IllegalMonitorException if object is not locked by current thread. +void InterpreterMacroAssembler::unlock_object(Register monitor) { + if (UseHeavyMonitors) { + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), + monitor, /*check_for_exceptions=*/false); + } else { + + // template code: + // + // if ((displaced_header = monitor->displaced_header()) == NULL) { + // // Recursive unlock. Mark the monitor unlocked by setting the object field to NULL. + // monitor->set_obj(NULL); + // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) { + // // We swapped the unlocked mark in displaced_header into the object's mark word. + // monitor->set_obj(NULL); + // } else { + // // Slow path. + // InterpreterRuntime::monitorexit(THREAD, monitor); + // } + + const Register object = R7_ARG5; + const Register displaced_header = R8_ARG6; + const Register object_mark_addr = R9_ARG7; + const Register current_header = R10_ARG8; + + Label no_recursive_unlock; + Label slow_case; + Label done; + + assert_different_registers(object, displaced_header, object_mark_addr, current_header); + + if (UseBiasedLocking) { + // The object address from the monitor is in object. + ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + biased_locking_exit(CCR0, object, displaced_header, done); + } + + // Test first if we are in the fast recursive case. + ld(displaced_header, BasicObjectLock::lock_offset_in_bytes() + + BasicLock::displaced_header_offset_in_bytes(), monitor); + + // If the displaced header is zero, we have a recursive unlock. + cmpdi(CCR0, displaced_header, 0); + bne(CCR0, no_recursive_unlock); + // Release in recursive unlock is not necessary. + // release(); + std(displaced_header/*==0!*/, BasicObjectLock::obj_offset_in_bytes(), monitor); + b(done); + + bind(no_recursive_unlock); + + // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) { + // // We swapped the unlocked mark in displaced_header into the object's mark word. + // monitor->set_obj(NULL); + + // If we still have a lightweight lock, unlock the object and be done. + + // The object address from the monitor is in object. + ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); + addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes()); + + // We have the displaced header in displaced_header. If the lock is still + // lightweight, it will contain the monitor address and we'll store the + // displaced header back into the object's mark word. + // CmpxchgX sets CCR0 to cmpX(current, monitor). + cmpxchgd(/*flag=*/CCR0, + /*current_value=*/current_header, + /*compare_value=*/monitor, /*exchange_value=*/displaced_header, + /*where=*/object_mark_addr, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_release_lock()); + bne(CCR0, slow_case); + + // Exchange worked, do monitor->set_obj(NULL). + li(R0, 0); + // Must realease earlier (see cmpxchgd above). + // release(); + std(R0, BasicObjectLock::obj_offset_in_bytes(), monitor); + b(done); + + + // } else { + // // Slow path. + // InterpreterRuntime::monitorexit(THREAD, monitor); + + // The lock has been converted into a heavy lock and hence + // we need to get into the slow case. + bind(slow_case); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), + monitor, /*check_for_exceptions=*/false); + // } + + bind(done); + } +} + +void InterpreterMacroAssembler::get_method_counters(Register method, + Register Rcounters, + Label& skip) { + BLOCK_COMMENT("Load and ev. allocate counter object {"); + Label has_counters; + ld(Rcounters, in_bytes(Method::method_counters_offset()), method); + cmpdi(CCR0, Rcounters, 0); + bne(CCR0, has_counters); + call_VM(noreg, CAST_FROM_FN_PTR(address, + InterpreterRuntime::build_method_counters), method, false); + ld(Rcounters, in_bytes(Method::method_counters_offset()), method); + cmpdi(CCR0, Rcounters, 0); + beq(CCR0, skip); // No MethodCounters, OutOfMemory. + BLOCK_COMMENT("} Load and ev. allocate counter object"); + + bind(has_counters); +} + +void InterpreterMacroAssembler::increment_invocation_counter(Register Rcounters, Register iv_be_count, Register Rtmp_r0) { + assert(UseCompiler, "incrementing must be useful"); + Register invocation_count = iv_be_count; + Register backedge_count = Rtmp_r0; + int delta = InvocationCounter::count_increment; + + // Load each counter in a register. + // ld(inv_counter, Rtmp); + // ld(be_counter, Rtmp2); + int inv_counter_offset = in_bytes(MethodCounters::invocation_counter_offset() + + InvocationCounter::counter_offset()); + int be_counter_offset = in_bytes(MethodCounters::backedge_counter_offset() + + InvocationCounter::counter_offset()); + + BLOCK_COMMENT("Increment profiling counters {"); + + // Load the backedge counter. + lwz(backedge_count, be_counter_offset, Rcounters); // is unsigned int + // Mask the backedge counter. + Register tmp = invocation_count; + li(tmp, InvocationCounter::count_mask_value); + andr(backedge_count, tmp, backedge_count); // Cannot use andi, need sign extension of count_mask_value. + + // Load the invocation counter. + lwz(invocation_count, inv_counter_offset, Rcounters); // is unsigned int + // Add the delta to the invocation counter and store the result. + addi(invocation_count, invocation_count, delta); + // Store value. + stw(invocation_count, inv_counter_offset, Rcounters); + + // Add invocation counter + backedge counter. + add(iv_be_count, backedge_count, invocation_count); + + // Note that this macro must leave the backedge_count + invocation_count in + // register iv_be_count! + BLOCK_COMMENT("} Increment profiling counters"); +} + +void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { + if (state == atos) { MacroAssembler::verify_oop(reg); } +} + +// Inline assembly for: +// +// if (thread is in interp_only_mode) { +// InterpreterRuntime::post_method_entry(); +// } +// if (*jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_ENTRY ) || +// *jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_ENTRY2) ) { +// SharedRuntime::jvmpi_method_entry(method, receiver); +// } +void InterpreterMacroAssembler::notify_method_entry() { + // JVMTI + // Whenever JVMTI puts a thread in interp_only_mode, method + // entry/exit events are sent for that thread to track stack + // depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + if (JvmtiExport::can_post_interpreter_events()) { + Label jvmti_post_done; + + lwz(R0, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); + cmpwi(CCR0, R0, 0); + beq(CCR0, jvmti_post_done); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry), + /*check_exceptions=*/false); + + bind(jvmti_post_done); + } +} + + +// Inline assembly for: +// +// if (thread is in interp_only_mode) { +// // save result +// InterpreterRuntime::post_method_exit(); +// // restore result +// } +// if (*jvmpi::event_flags_array_at_addr(JVMPI_EVENT_METHOD_EXIT)) { +// // save result +// SharedRuntime::jvmpi_method_exit(); +// // restore result +// } +// +// Native methods have their result stored in d_tmp and l_tmp. +// Java methods have their result stored in the expression stack. +void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, TosState state) { + // JVMTI + // Whenever JVMTI puts a thread in interp_only_mode, method + // entry/exit events are sent for that thread to track stack + // depth. If it is possible to enter interp_only_mode we add + // the code to check if the event should be sent. + if (JvmtiExport::can_post_interpreter_events()) { + Label jvmti_post_done; + + lwz(R0, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); + cmpwi(CCR0, R0, 0); + beq(CCR0, jvmti_post_done); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit), + /*check_exceptions=*/false); + + bind(jvmti_post_done); + } +} + +// Convert the current TOP_IJAVA_FRAME into a PARENT_IJAVA_FRAME +// (using parent_frame_resize) and push a new interpreter +// TOP_IJAVA_FRAME (using frame_size). +void InterpreterMacroAssembler::push_interpreter_frame(Register top_frame_size, Register parent_frame_resize, + Register tmp1, Register tmp2, Register tmp3, + Register tmp4, Register pc) { + assert_different_registers(top_frame_size, parent_frame_resize, tmp1, tmp2, tmp3, tmp4); + ld(tmp1, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + mr(tmp2/*top_frame_sp*/, R1_SP); + // Move initial_caller_sp. + ld(tmp4, _top_ijava_frame_abi(initial_caller_sp), R1_SP); + neg(parent_frame_resize, parent_frame_resize); + resize_frame(parent_frame_resize/*-parent_frame_resize*/, tmp3); + + // Set LR in new parent frame. + std(tmp1, _abi(lr), R1_SP); + // Set top_frame_sp info for new parent frame. + std(tmp2, _parent_ijava_frame_abi(top_frame_sp), R1_SP); + std(tmp4, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); + + // Push new TOP_IJAVA_FRAME. + push_frame(top_frame_size, tmp2); + + get_PC_trash_LR(tmp3); + std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + // Used for non-initial callers by unextended_sp(). + std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); +} + +// Pop the topmost TOP_IJAVA_FRAME and convert the previous +// PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. +void InterpreterMacroAssembler::pop_interpreter_frame(Register tmp1, Register tmp2, Register tmp3, Register tmp4) { + assert_different_registers(tmp1, tmp2, tmp3, tmp4); + + ld(tmp1/*caller's sp*/, _abi(callers_sp), R1_SP); + ld(tmp3, _abi(lr), tmp1); + + ld(tmp4, _parent_ijava_frame_abi(initial_caller_sp), tmp1); + + ld(tmp2/*caller's caller's sp*/, _abi(callers_sp), tmp1); + // Merge top frame. + std(tmp2, _abi(callers_sp), R1_SP); + + ld(tmp2, _parent_ijava_frame_abi(top_frame_sp), tmp1); + + // Update C stack pointer to caller's top_abi. + resize_frame_absolute(tmp2/*addr*/, tmp1/*tmp*/, tmp2/*tmp*/); + + // Update LR in top_frame. + std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + + std(tmp4, _top_ijava_frame_abi(initial_caller_sp), R1_SP); + + // Store the top-frame stack-pointer for c2i adapters. + std(R1_SP, _top_ijava_frame_abi(top_frame_sp), R1_SP); +} + +#ifdef CC_INTERP +// Turn state's interpreter frame into the current TOP_IJAVA_FRAME. +void InterpreterMacroAssembler::pop_interpreter_frame_to_state(Register state, Register tmp1, Register tmp2, Register tmp3) { + assert_different_registers(R14_state, R15_prev_state, tmp1, tmp2, tmp3); + + if (state == R14_state) { + ld(tmp1/*state's fp*/, state_(_last_Java_fp)); + ld(tmp2/*state's sp*/, state_(_last_Java_sp)); + } else if (state == R15_prev_state) { + ld(tmp1/*state's fp*/, prev_state_(_last_Java_fp)); + ld(tmp2/*state's sp*/, prev_state_(_last_Java_sp)); + } else { + ShouldNotReachHere(); + } + + // Merge top frames. + std(tmp1, _abi(callers_sp), R1_SP); + + // Tmp2 is new SP. + // Tmp1 is parent's SP. + resize_frame_absolute(tmp2/*addr*/, tmp1/*tmp*/, tmp2/*tmp*/); + + // Update LR in top_frame. + // Must be interpreter frame. + get_PC_trash_LR(tmp3); + std(tmp3, _top_ijava_frame_abi(frame_manager_lr), R1_SP); + // Used for non-initial callers by unextended_sp(). + std(R1_SP, _top_ijava_frame_abi(initial_caller_sp), R1_SP); +} +#endif // CC_INTERP + +// Set SP to initial caller's sp, but before fix the back chain. +void InterpreterMacroAssembler::resize_frame_to_initial_caller(Register tmp1, Register tmp2) { + ld(tmp1, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); + ld(tmp2, _parent_ijava_frame_abi(callers_sp), R1_SP); + std(tmp2, _parent_ijava_frame_abi(callers_sp), tmp1); // Fix back chain ... + mr(R1_SP, tmp1); // ... and resize to initial caller. +} + +#ifdef CC_INTERP +// Pop the current interpreter state (without popping the correspoding +// frame) and restore R14_state and R15_prev_state accordingly. +// Use prev_state_may_be_0 to indicate whether prev_state may be 0 +// in order to generate an extra check before retrieving prev_state_(_prev_link). +void InterpreterMacroAssembler::pop_interpreter_state(bool prev_state_may_be_0) +{ + // Move prev_state to state and restore prev_state from state_(_prev_link). + Label prev_state_is_0; + mr(R14_state, R15_prev_state); + + // Don't retrieve /*state==*/prev_state_(_prev_link) + // if /*state==*/prev_state is 0. + if (prev_state_may_be_0) { + cmpdi(CCR0, R15_prev_state, 0); + beq(CCR0, prev_state_is_0); + } + + ld(R15_prev_state, /*state==*/prev_state_(_prev_link)); + bind(prev_state_is_0); +} + +void InterpreterMacroAssembler::restore_prev_state() { + // _prev_link is private, but cInterpreter is a friend. + ld(R15_prev_state, state_(_prev_link)); +} +#endif // CC_INTERP diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp new file mode 100644 index 00000000000..d4d3f165dbe --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_INTERP_MASM_PPC_64_HPP +#define CPU_PPC_VM_INTERP_MASM_PPC_64_HPP + +#include "assembler_ppc.inline.hpp" +#include "interpreter/invocationCounter.hpp" + +// This file specializes the assembler with interpreter-specific macros + + +class InterpreterMacroAssembler: public MacroAssembler { + + public: + InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {} + + // Handy address generation macros +#define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread +#define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method + +#ifdef CC_INTERP +#define state_(field_name) in_bytes(byte_offset_of(BytecodeInterpreter, field_name)), R14_state +#define prev_state_(field_name) in_bytes(byte_offset_of(BytecodeInterpreter, field_name)), R15_prev_state +#endif + + void get_method_counters(Register method, Register Rcounters, Label& skip); + void increment_invocation_counter(Register iv_be_count, Register Rtmp1, Register Rtmp2_r0); + + // Object locking + void lock_object (Register lock_reg, Register obj_reg); + void unlock_object(Register lock_reg); + + // Debugging + void verify_oop(Register reg, TosState state = atos); // only if +VerifyOops && state == atos + + // support for jvmdi/jvmpi + void notify_method_entry(); + void notify_method_exit(bool save_result, TosState state); + + // Convert the current TOP_IJAVA_FRAME into a PARENT_IJAVA_FRAME + // (using parent_frame_resize) and push a new interpreter + // TOP_IJAVA_FRAME (using frame_size). + void push_interpreter_frame(Register top_frame_size, Register parent_frame_resize, + Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register pc=noreg); + + // Pop the topmost TOP_IJAVA_FRAME and convert the previous + // PARENT_IJAVA_FRAME back into a TOP_IJAVA_FRAME. + void pop_interpreter_frame(Register tmp1, Register tmp2, Register tmp3, Register tmp4); + + // Turn state's interpreter frame into the current TOP_IJAVA_FRAME. + void pop_interpreter_frame_to_state(Register state, Register tmp1, Register tmp2, Register tmp3); + + // Set SP to initial caller's sp, but before fix the back chain. + void resize_frame_to_initial_caller(Register tmp1, Register tmp2); + + // Pop the current interpreter state (without popping the + // correspoding frame) and restore R14_state and R15_prev_state + // accordingly. Use prev_state_may_be_0 to indicate whether + // prev_state may be 0 in order to generate an extra check before + // retrieving prev_state_(_prev_link). + void pop_interpreter_state(bool prev_state_may_be_0); + + void restore_prev_state(); +}; + +#endif // CPU_PPC_VM_INTERP_MASM_PPC_64_HPP diff --git a/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp b/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp new file mode 100644 index 00000000000..74f6001e766 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP +#define CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP + + friend class AbstractInterpreterGenerator; + + private: + + address generate_abstract_entry(void); + address generate_accessor_entry(void); + address generate_Reference_get_entry(void); + +#endif // CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.cpp b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.cpp new file mode 100644 index 00000000000..3a1389f413b --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/universe.inline.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/icache.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/signature.hpp" + +#define __ _masm-> + +// Access macros for Java and C arguments. +// The first Java argument is at index -1. +#define locals_j_arg_at(index) (Interpreter::local_offset_in_bytes(index)), R18_locals +// The first C argument is at index 0. +#define sp_c_arg_at(index) ((index)*wordSize + _abi(carg_1)), R1_SP + +// Implementation of SignatureHandlerGenerator + +void InterpreterRuntime::SignatureHandlerGenerator::pass_int() { + Argument jni_arg(jni_offset()); + Register r = jni_arg.is_register() ? jni_arg.as_register() : R0; + + __ lwa(r, locals_j_arg_at(offset())); // sign extension of integer + if (DEBUG_ONLY(true ||) !jni_arg.is_register()) { + __ std(r, sp_c_arg_at(jni_arg.number())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { + Argument jni_arg(jni_offset()); + Register r = jni_arg.is_register() ? jni_arg.as_register() : R0; + + __ ld(r, locals_j_arg_at(offset()+1)); // long resides in upper slot + if (DEBUG_ONLY(true ||) !jni_arg.is_register()) { + __ std(r, sp_c_arg_at(jni_arg.number())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { + FloatRegister fp_reg = (_num_used_fp_arg_regs < 13/*max_fp_register_arguments*/) + ? as_FloatRegister((_num_used_fp_arg_regs++) + F1_ARG1->encoding()) + : F0; + + __ lfs(fp_reg, locals_j_arg_at(offset())); + if (DEBUG_ONLY(true ||) jni_offset() > 8) { + __ stfs(fp_reg, sp_c_arg_at(jni_offset())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { + FloatRegister fp_reg = (_num_used_fp_arg_regs < 13/*max_fp_register_arguments*/) + ? as_FloatRegister((_num_used_fp_arg_regs++) + F1_ARG1->encoding()) + : F0; + + __ lfd(fp_reg, locals_j_arg_at(offset()+1)); + if (DEBUG_ONLY(true ||) jni_offset() > 8) { + __ stfd(fp_reg, sp_c_arg_at(jni_offset())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { + Argument jni_arg(jni_offset()); + Register r = jni_arg.is_register() ? jni_arg.as_register() : R11_scratch1; + + // The handle for a receiver will never be null. + bool do_NULL_check = offset() != 0 || is_static(); + + Label do_null; + if (do_NULL_check) { + __ ld(R0, locals_j_arg_at(offset())); + __ cmpdi(CCR0, R0, 0); + __ li(r, 0); + __ beq(CCR0, do_null); + } + __ addir(r, locals_j_arg_at(offset())); + __ bind(do_null); + if (DEBUG_ONLY(true ||) !jni_arg.is_register()) { + __ std(r, sp_c_arg_at(jni_arg.number())); + } +} + +void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) { + // Emit fd for current codebuffer. Needs patching! + __ emit_fd(); + + // Generate code to handle arguments. + iterate(fingerprint); + + // Return the result handler. + __ load_const(R3_RET, AbstractInterpreter::result_handler(method()->result_type())); + __ blr(); + + __ flush(); +} + +#undef __ + +// Implementation of SignatureHandlerLibrary + +void SignatureHandlerLibrary::pd_set_handler(address handler) { + // patch fd here. + FunctionDescriptor* fd = (FunctionDescriptor*) handler; + + fd->set_entry(handler + (int)sizeof(FunctionDescriptor)); + assert(fd->toc() == (address)0xcafe, "need to adjust TOC here"); +} + + +// Access function to get the signature. +IRT_ENTRY(address, InterpreterRuntime::get_signature(JavaThread* thread, Method* method)) + methodHandle m(thread, method); + assert(m->is_native(), "sanity check"); + Symbol *s = m->signature(); + return (address) s->base(); +IRT_END + +IRT_ENTRY(address, InterpreterRuntime::get_result_handler(JavaThread* thread, Method* method)) + methodHandle m(thread, method); + assert(m->is_native(), "sanity check"); + return AbstractInterpreter::result_handler(m->result_type()); +IRT_END diff --git a/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp new file mode 100644 index 00000000000..144ef50bfa8 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_INTERPRETERRT_PPC_HPP +#define CPU_PPC_VM_INTERPRETERRT_PPC_HPP + +#include "memory/allocation.hpp" + +// native method calls + +class SignatureHandlerGenerator: public NativeSignatureIterator { + private: + MacroAssembler* _masm; + // number of already used floating-point argument registers + int _num_used_fp_arg_regs; + + void pass_int(); + void pass_long(); + void pass_double(); + void pass_float(); + void pass_object(); + + public: + // Creation + SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + _masm = new MacroAssembler(buffer); + _num_used_fp_arg_regs = 0; + } + + // Code generation + void generate(uint64_t fingerprint); +}; + +// Support for generate_slow_signature_handler. +static address get_result_handler(JavaThread* thread, Method* method); + +// A function to get the signature. +static address get_signature(JavaThread* thread, Method* method); + +#endif // CPU_PPC_VM_INTERPRETERRT_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp new file mode 100644 index 00000000000..9e3d61a8367 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp @@ -0,0 +1,736 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "interpreter/bytecodeHistogram.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterGenerator.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/templateTable.hpp" +#include "oops/arrayOop.hpp" +#include "oops/methodData.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/arguments.hpp" +#include "runtime/deoptimization.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/timer.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif + +#ifndef CC_INTERP +#error "CC_INTERP must be defined on PPC" +#endif + +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +int AbstractInterpreter::BasicType_as_index(BasicType type) { + int i = 0; + switch (type) { + case T_BOOLEAN: i = 0; break; + case T_CHAR : i = 1; break; + case T_BYTE : i = 2; break; + case T_SHORT : i = 3; break; + case T_INT : i = 4; break; + case T_LONG : i = 5; break; + case T_VOID : i = 6; break; + case T_FLOAT : i = 7; break; + case T_DOUBLE : i = 8; break; + case T_OBJECT : i = 9; break; + case T_ARRAY : i = 9; break; + default : ShouldNotReachHere(); + } + assert(0 <= i && i < AbstractInterpreter::number_of_result_handlers, "index out of bounds"); + return i; +} + +address AbstractInterpreterGenerator::generate_slow_signature_handler() { + // Slow_signature handler that respects the PPC C calling conventions. + // + // We get called by the native entry code with our output register + // area == 8. First we call InterpreterRuntime::get_result_handler + // to copy the pointer to the signature string temporarily to the + // first C-argument and to return the result_handler in + // R3_RET. Since native_entry will copy the jni-pointer to the + // first C-argument slot later on, it is OK to occupy this slot + // temporarilly. Then we copy the argument list on the java + // expression stack into native varargs format on the native stack + // and load arguments into argument registers. Integer arguments in + // the varargs vector will be sign-extended to 8 bytes. + // + // On entry: + // R3_ARG1 - intptr_t* Address of java argument list in memory. + // R15_prev_state - BytecodeInterpreter* Address of interpreter state for + // this method + // R19_method + // + // On exit (just before return instruction): + // R3_RET - contains the address of the result_handler. + // R4_ARG2 - is not updated for static methods and contains "this" otherwise. + // R5_ARG3-R10_ARG8: - When the (i-2)th Java argument is not of type float or double, + // ARGi contains this argument. Otherwise, ARGi is not updated. + // F1_ARG1-F13_ARG13 - contain the first 13 arguments of type float or double. + + const int LogSizeOfTwoInstructions = 3; + + // FIXME: use Argument:: GL: Argument names different numbers! + const int max_fp_register_arguments = 13; + const int max_int_register_arguments = 6; // first 2 are reserved + + const Register arg_java = R21_tmp1; + const Register arg_c = R22_tmp2; + const Register signature = R23_tmp3; // is string + const Register sig_byte = R24_tmp4; + const Register fpcnt = R25_tmp5; + const Register argcnt = R26_tmp6; + const Register intSlot = R27_tmp7; + const Register target_sp = R28_tmp8; + const FloatRegister floatSlot = F0; + + address entry = __ emit_fd(); + + __ save_LR_CR(R0); + __ save_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); + // We use target_sp for storing arguments in the C frame. + __ mr(target_sp, R1_SP); + __ push_frame_abi112_nonvolatiles(0, R11_scratch1); + + __ mr(arg_java, R3_ARG1); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::get_signature), R16_thread, R19_method); + + // Signature is in R3_RET. Signature is callee saved. + __ mr(signature, R3_RET); + + // Reload method, it may have moved. +#ifdef CC_INTERP + __ ld(R19_method, state_(_method)); +#else + __ unimplemented("slow signature handler 1"); +#endif + + // Get the result handler. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::get_result_handler), R16_thread, R19_method); + + // Reload method, it may have moved. +#ifdef CC_INTERP + __ ld(R19_method, state_(_method)); +#else + __ unimplemented("slow signature handler 2"); +#endif + + { + Label L; + // test if static + // _access_flags._flags must be at offset 0. + // TODO PPC port: requires change in shared code. + //assert(in_bytes(AccessFlags::flags_offset()) == 0, + // "MethodOopDesc._access_flags == MethodOopDesc._access_flags._flags"); + // _access_flags must be a 32 bit value. + assert(sizeof(AccessFlags) == 4, "wrong size"); + __ lwa(R11_scratch1/*access_flags*/, method_(access_flags)); + // testbit with condition register. + __ testbitdi(CCR0, R0, R11_scratch1/*access_flags*/, JVM_ACC_STATIC_BIT); + __ btrue(CCR0, L); + // For non-static functions, pass "this" in R4_ARG2 and copy it + // to 2nd C-arg slot. + // We need to box the Java object here, so we use arg_java + // (address of current Java stack slot) as argument and don't + // dereference it as in case of ints, floats, etc. + __ mr(R4_ARG2, arg_java); + __ addi(arg_java, arg_java, -BytesPerWord); + __ std(R4_ARG2, _abi(carg_2), target_sp); + __ bind(L); + } + + // Will be incremented directly after loop_start. argcnt=0 + // corresponds to 3rd C argument. + __ li(argcnt, -1); + // arg_c points to 3rd C argument + __ addi(arg_c, target_sp, _abi(carg_3)); + // no floating-point args parsed so far + __ li(fpcnt, 0); + + Label move_intSlot_to_ARG, move_floatSlot_to_FARG; + Label loop_start, loop_end; + Label do_int, do_long, do_float, do_double, do_dontreachhere, do_object, do_array, do_boxed; + + // signature points to '(' at entry +#ifdef ASSERT + __ lbz(sig_byte, 0, signature); + __ cmplwi(CCR0, sig_byte, '('); + __ bne(CCR0, do_dontreachhere); +#endif + + __ bind(loop_start); + + __ addi(argcnt, argcnt, 1); + __ lbzu(sig_byte, 1, signature); + + __ cmplwi(CCR0, sig_byte, ')'); // end of signature + __ beq(CCR0, loop_end); + + __ cmplwi(CCR0, sig_byte, 'B'); // byte + __ beq(CCR0, do_int); + + __ cmplwi(CCR0, sig_byte, 'C'); // char + __ beq(CCR0, do_int); + + __ cmplwi(CCR0, sig_byte, 'D'); // double + __ beq(CCR0, do_double); + + __ cmplwi(CCR0, sig_byte, 'F'); // float + __ beq(CCR0, do_float); + + __ cmplwi(CCR0, sig_byte, 'I'); // int + __ beq(CCR0, do_int); + + __ cmplwi(CCR0, sig_byte, 'J'); // long + __ beq(CCR0, do_long); + + __ cmplwi(CCR0, sig_byte, 'S'); // short + __ beq(CCR0, do_int); + + __ cmplwi(CCR0, sig_byte, 'Z'); // boolean + __ beq(CCR0, do_int); + + __ cmplwi(CCR0, sig_byte, 'L'); // object + __ beq(CCR0, do_object); + + __ cmplwi(CCR0, sig_byte, '['); // array + __ beq(CCR0, do_array); + + // __ cmplwi(CCR0, sig_byte, 'V'); // void cannot appear since we do not parse the return type + // __ beq(CCR0, do_void); + + __ bind(do_dontreachhere); + + __ unimplemented("ShouldNotReachHere in slow_signature_handler", 120); + + __ bind(do_array); + + { + Label start_skip, end_skip; + + __ bind(start_skip); + __ lbzu(sig_byte, 1, signature); + __ cmplwi(CCR0, sig_byte, '['); + __ beq(CCR0, start_skip); // skip further brackets + __ cmplwi(CCR0, sig_byte, '9'); + __ bgt(CCR0, end_skip); // no optional size + __ cmplwi(CCR0, sig_byte, '0'); + __ bge(CCR0, start_skip); // skip optional size + __ bind(end_skip); + + __ cmplwi(CCR0, sig_byte, 'L'); + __ beq(CCR0, do_object); // for arrays of objects, the name of the object must be skipped + __ b(do_boxed); // otherwise, go directly to do_boxed + } + + __ bind(do_object); + { + Label L; + __ bind(L); + __ lbzu(sig_byte, 1, signature); + __ cmplwi(CCR0, sig_byte, ';'); + __ bne(CCR0, L); + } + // Need to box the Java object here, so we use arg_java (address of + // current Java stack slot) as argument and don't dereference it as + // in case of ints, floats, etc. + Label do_null; + __ bind(do_boxed); + __ ld(R0,0, arg_java); + __ cmpdi(CCR0, R0, 0); + __ li(intSlot,0); + __ beq(CCR0, do_null); + __ mr(intSlot, arg_java); + __ bind(do_null); + __ std(intSlot, 0, arg_c); + __ addi(arg_java, arg_java, -BytesPerWord); + __ addi(arg_c, arg_c, BytesPerWord); + __ cmplwi(CCR0, argcnt, max_int_register_arguments); + __ blt(CCR0, move_intSlot_to_ARG); + __ b(loop_start); + + __ bind(do_int); + __ lwa(intSlot, 0, arg_java); + __ std(intSlot, 0, arg_c); + __ addi(arg_java, arg_java, -BytesPerWord); + __ addi(arg_c, arg_c, BytesPerWord); + __ cmplwi(CCR0, argcnt, max_int_register_arguments); + __ blt(CCR0, move_intSlot_to_ARG); + __ b(loop_start); + + __ bind(do_long); + __ ld(intSlot, -BytesPerWord, arg_java); + __ std(intSlot, 0, arg_c); + __ addi(arg_java, arg_java, - 2 * BytesPerWord); + __ addi(arg_c, arg_c, BytesPerWord); + __ cmplwi(CCR0, argcnt, max_int_register_arguments); + __ blt(CCR0, move_intSlot_to_ARG); + __ b(loop_start); + + __ bind(do_float); + __ lfs(floatSlot, 0, arg_java); +#if defined(LINUX) + __ stfs(floatSlot, 4, arg_c); +#elif defined(AIX) + __ stfs(floatSlot, 0, arg_c); +#else +#error "unknown OS" +#endif + __ addi(arg_java, arg_java, -BytesPerWord); + __ addi(arg_c, arg_c, BytesPerWord); + __ cmplwi(CCR0, fpcnt, max_fp_register_arguments); + __ blt(CCR0, move_floatSlot_to_FARG); + __ b(loop_start); + + __ bind(do_double); + __ lfd(floatSlot, - BytesPerWord, arg_java); + __ stfd(floatSlot, 0, arg_c); + __ addi(arg_java, arg_java, - 2 * BytesPerWord); + __ addi(arg_c, arg_c, BytesPerWord); + __ cmplwi(CCR0, fpcnt, max_fp_register_arguments); + __ blt(CCR0, move_floatSlot_to_FARG); + __ b(loop_start); + + __ bind(loop_end); + + __ pop_frame(); + __ restore_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); + __ restore_LR_CR(R0); + + __ blr(); + + Label move_int_arg, move_float_arg; + __ bind(move_int_arg); // each case must consist of 2 instructions (otherwise adapt LogSizeOfTwoInstructions) + __ mr(R5_ARG3, intSlot); __ b(loop_start); + __ mr(R6_ARG4, intSlot); __ b(loop_start); + __ mr(R7_ARG5, intSlot); __ b(loop_start); + __ mr(R8_ARG6, intSlot); __ b(loop_start); + __ mr(R9_ARG7, intSlot); __ b(loop_start); + __ mr(R10_ARG8, intSlot); __ b(loop_start); + + __ bind(move_float_arg); // each case must consist of 2 instructions (otherwise adapt LogSizeOfTwoInstructions) + __ fmr(F1_ARG1, floatSlot); __ b(loop_start); + __ fmr(F2_ARG2, floatSlot); __ b(loop_start); + __ fmr(F3_ARG3, floatSlot); __ b(loop_start); + __ fmr(F4_ARG4, floatSlot); __ b(loop_start); + __ fmr(F5_ARG5, floatSlot); __ b(loop_start); + __ fmr(F6_ARG6, floatSlot); __ b(loop_start); + __ fmr(F7_ARG7, floatSlot); __ b(loop_start); + __ fmr(F8_ARG8, floatSlot); __ b(loop_start); + __ fmr(F9_ARG9, floatSlot); __ b(loop_start); + __ fmr(F10_ARG10, floatSlot); __ b(loop_start); + __ fmr(F11_ARG11, floatSlot); __ b(loop_start); + __ fmr(F12_ARG12, floatSlot); __ b(loop_start); + __ fmr(F13_ARG13, floatSlot); __ b(loop_start); + + __ bind(move_intSlot_to_ARG); + __ sldi(R0, argcnt, LogSizeOfTwoInstructions); + __ load_const(R11_scratch1, move_int_arg); // Label must be bound here. + __ add(R11_scratch1, R0, R11_scratch1); + __ mtctr(R11_scratch1/*branch_target*/); + __ bctr(); + __ bind(move_floatSlot_to_FARG); + __ sldi(R0, fpcnt, LogSizeOfTwoInstructions); + __ addi(fpcnt, fpcnt, 1); + __ load_const(R11_scratch1, move_float_arg); // Label must be bound here. + __ add(R11_scratch1, R0, R11_scratch1); + __ mtctr(R11_scratch1/*branch_target*/); + __ bctr(); + + return entry; +} + +address AbstractInterpreterGenerator::generate_result_handler_for(BasicType type) { + // + // Registers alive + // R3_RET + // LR + // + // Registers updated + // R3_RET + // + + Label done; + Label is_false; + + address entry = __ pc(); + + switch (type) { + case T_BOOLEAN: + __ cmpwi(CCR0, R3_RET, 0); + __ beq(CCR0, is_false); + __ li(R3_RET, 1); + __ b(done); + __ bind(is_false); + __ li(R3_RET, 0); + break; + case T_BYTE: + // sign extend 8 bits + __ extsb(R3_RET, R3_RET); + break; + case T_CHAR: + // zero extend 16 bits + __ clrldi(R3_RET, R3_RET, 48); + break; + case T_SHORT: + // sign extend 16 bits + __ extsh(R3_RET, R3_RET); + break; + case T_INT: + // sign extend 32 bits + __ extsw(R3_RET, R3_RET); + break; + case T_LONG: + break; + case T_OBJECT: + // unbox result if not null + __ cmpdi(CCR0, R3_RET, 0); + __ beq(CCR0, done); + __ ld(R3_RET, 0, R3_RET); + __ verify_oop(R3_RET); + break; + case T_FLOAT: + break; + case T_DOUBLE: + break; + case T_VOID: + break; + default: ShouldNotReachHere(); + } + + __ BIND(done); + __ blr(); + + return entry; +} + +// Abstract method entry. +// +address InterpreterGenerator::generate_abstract_entry(void) { + address entry = __ pc(); + + // + // Registers alive + // R16_thread - JavaThread* + // R19_method - callee's methodOop (method to be invoked) + // R1_SP - SP prepared such that caller's outgoing args are near top + // LR - return address to caller + // + // Stack layout at this point: + // + // 0 [TOP_IJAVA_FRAME_ABI] <-- R1_SP + // alignment (optional) + // [outgoing Java arguments] + // ... + // PARENT [PARENT_IJAVA_FRAME_ABI] + // ... + // + + // Can't use call_VM here because we have not set up a new + // interpreter state. Make the call to the vm and make it look like + // our caller set up the JavaFrameAnchor. + __ set_top_ijava_frame_at_SP_as_last_Java_frame(R1_SP, R12_scratch2/*tmp*/); + + // Push a new C frame and save LR. + __ save_LR_CR(R0); + __ push_frame_abi112_nonvolatiles(0, R11_scratch1); + + // This is not a leaf but we have a JavaFrameAnchor now and we will + // check (create) exceptions afterward so this is ok. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); + + // Pop the C frame and restore LR. + __ pop_frame(); + __ restore_LR_CR(R0); + + // Reset JavaFrameAnchor from call_VM_leaf above. + __ reset_last_Java_frame(); + + // Return to frame manager, it will handle the pending exception. + __ blr(); + + return entry; +} + +// Call an accessor method (assuming it is resolved, otherwise drop into +// vanilla (slow path) entry. +address InterpreterGenerator::generate_accessor_entry(void) { + if(!UseFastAccessorMethods && (!FLAG_IS_ERGO(UseFastAccessorMethods))) + return NULL; + + Label Ldone, Lslow_path; + + const Register Rthis = R3_ARG1, + Rconst_method = R4_ARG2, + Rcodes = Rconst_method, + Rcpool_cache = R5_ARG3, + Rscratch = R11_scratch1, + Rjvmti_mode = Rscratch, + Roffset = R12_scratch2, + Rflags = R6_ARG4; + + address entry = __ pc(); + + // Check for safepoint: + // Ditch this, real man don't need safepoint checks. + + // Also check for JVMTI mode + // Check for null obj, take slow path if so. +#ifdef CC_INTERP + __ ld(Rthis, Interpreter::stackElementSize, R17_tos); +#else + Unimplemented() +#endif + __ lwz(Rjvmti_mode, thread_(interp_only_mode)); + __ cmpdi(CCR1, Rthis, 0); + __ cmpwi(CCR0, Rjvmti_mode, 0); + __ crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); + __ beq(CCR0, Lslow_path); // this==null or jvmti_mode!=0 + + // Do 2 things in parallel: + // 1. Load the index out of the first instruction word, which looks like this: + // <0x2a><0xb4>. + // 2. Load constant pool cache base. + __ ld(Rconst_method, in_bytes(Method::const_offset()), R19_method); + __ ld(Rcpool_cache, in_bytes(ConstMethod::constants_offset()), Rconst_method); + + __ lhz(Rcodes, in_bytes(ConstMethod::codes_offset()) + 2, Rconst_method); // Lower half of 32 bit field. + __ ld(Rcpool_cache, ConstantPool::cache_offset_in_bytes(), Rcpool_cache); + + // Get the const pool entry by means of . + const int codes_shift = exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord); + __ slwi(Rscratch, Rcodes, codes_shift); // (codes&0xFFFF)<>ConstantPoolCacheEntry::tos_state_shift)&((1< 0, "referent offset not initialized"); + + if (UseG1GC) { + Label slow_path; + + // Debugging not possible, so can't use __ skip_if_jvmti_mode(slow_path, GR31_SCRATCH); + + // In the G1 code we don't check if we need to reach a safepoint. We + // continue and the thread will safepoint at the next bytecode dispatch. + + // If the receiver is null then it is OK to jump to the slow path. +#ifdef CC_INTERP + __ ld(R3_RET, Interpreter::stackElementSize, R17_tos); // get receiver +#else + Unimplemented(); +#endif + + // Check if receiver == NULL and go the slow path. + __ cmpdi(CCR0, R3_RET, 0); + __ beq(CCR0, slow_path); + + // Load the value of the referent field. + __ load_heap_oop_not_null(R3_RET, referent_offset, R3_RET); + + // Generate the G1 pre-barrier code to log the value of + // the referent field in an SATB buffer. Note with + // these parameters the pre-barrier does not generate + // the load of the previous value. + + // Restore caller sp for c2i case. +#ifdef ASSERT + __ ld(R9_ARG7, 0, R1_SP); + __ ld(R10_ARG8, 0, R21_sender_SP); + __ cmpd(CCR0, R9_ARG7, R10_ARG8); + __ asm_assert_eq("backlink", 0x544); +#endif // ASSERT + __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. + + __ g1_write_barrier_pre(noreg, // obj + noreg, // offset + R3_RET, // pre_val + R11_scratch1, // tmp + R12_scratch2, // tmp + true); // needs_frame + + __ blr(); + + // Generate regular method entry. + __ bind(slow_path); + assert(Interpreter::entry_for_kind(Interpreter::zerolocals), "Normal entry must have been generated by now"); + __ load_const_optimized(R11_scratch1, Interpreter::entry_for_kind(Interpreter::zerolocals), R0); + __ mtctr(R11_scratch1); + __ bctr(); + __ flush(); + + return entry; + } else { + return generate_accessor_entry(); + } +} + +void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) { + // This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in + // the days we had adapter frames. When we deoptimize a situation where a + // compiled caller calls a compiled caller will have registers it expects + // to survive the call to the callee. If we deoptimize the callee the only + // way we can restore these registers is to have the oldest interpreter + // frame that we create restore these values. That is what this routine + // will accomplish. + + // At the moment we have modified c2 to not have any callee save registers + // so this problem does not exist and this routine is just a place holder. + + assert(f->is_interpreted_frame(), "must be interpreted"); +} diff --git a/hotspot/src/cpu/ppc/vm/interpreter_ppc.hpp b/hotspot/src/cpu/ppc/vm/interpreter_ppc.hpp new file mode 100644 index 00000000000..37bf8e9fe6b --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_INTERPRETER_PPC_HPP +#define CPU_PPC_VM_INTERPRETER_PPC_HPP + + public: + + // Stack index relative to tos (which points at value) + static int expr_index_at(int i) { + return stackElementWords * i; + } + + // Already negated by c++ interpreter + static int local_index_at(int i) { + assert(i <= 0, "local direction already negated"); + return stackElementWords * i; + } + +#endif // CPU_PPC_VM_INTERPRETER_PPC_PP diff --git a/hotspot/src/cpu/ppc/vm/javaFrameAnchor_ppc.hpp b/hotspot/src/cpu/ppc/vm/javaFrameAnchor_ppc.hpp new file mode 100644 index 00000000000..f12df9cbe76 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/javaFrameAnchor_ppc.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_JAVAFRAMEANCHOR_PPC_HPP +#define CPU_PPC_VM_JAVAFRAMEANCHOR_PPC_HPP + +#ifndef CC_INTERP +#error "CC_INTERP must be defined on PPC64" +#endif + +public: + // Each arch must define reset, save, restore + // These are used by objects that only care about: + // 1 - initializing a new state (thread creation, javaCalls) + // 2 - saving a current state (javaCalls) + // 3 - restoring an old state (javaCalls) + + inline void clear(void) { + // clearing _last_Java_sp must be first + _last_Java_sp = NULL; + // fence? + OrderAccess::release(); + _last_Java_pc = NULL; + } + + inline void set(intptr_t* sp, address pc) { + _last_Java_pc = pc; + OrderAccess::release(); + _last_Java_sp = sp; + } + + void copy(JavaFrameAnchor* src) { + // In order to make sure the transition state is valid for "this". + // We must clear _last_Java_sp before copying the rest of the new data. + // + // Hack Alert: Temporary bugfix for 4717480/4721647 + // To act like previous version (pd_cache_state) don't NULL _last_Java_sp + // unless the value is changing. + if (_last_Java_sp != src->_last_Java_sp) { + _last_Java_sp = NULL; + OrderAccess::release(); + } + _last_Java_pc = src->_last_Java_pc; + // Must be last so profiler will always see valid frame if has_last_frame() is true. + OrderAccess::release(); + _last_Java_sp = src->_last_Java_sp; + } + + // Always walkable. + bool walkable(void) { return true; } + // Never any thing to do since we are always walkable and can find address of return addresses. + void make_walkable(JavaThread* thread) { } + + intptr_t* last_Java_sp(void) const { return _last_Java_sp; } + + address last_Java_pc(void) { return _last_Java_pc; } + + void set_last_Java_sp(intptr_t* sp) { OrderAccess::release(); _last_Java_sp = sp; } + +#endif // CPU_PPC_VM_JAVAFRAMEANCHOR_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/jniFastGetField_ppc.cpp b/hotspot/src/cpu/ppc/vm/jniFastGetField_ppc.cpp new file mode 100644 index 00000000000..88cc7f1481d --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/jniFastGetField_ppc.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "assembler_ppc.inline.hpp" +#include "memory/resourceArea.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm_misc.hpp" +#include "runtime/safepoint.hpp" + + +address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { + // we don't have fast jni accessors. + return (address) -1; +} + +address JNI_FastGetField::generate_fast_get_boolean_field() { + return generate_fast_get_int_field0(T_BOOLEAN); +} + +address JNI_FastGetField::generate_fast_get_byte_field() { + return generate_fast_get_int_field0(T_BYTE); +} + +address JNI_FastGetField::generate_fast_get_char_field() { + return generate_fast_get_int_field0(T_CHAR); +} + +address JNI_FastGetField::generate_fast_get_short_field() { + return generate_fast_get_int_field0(T_SHORT); +} + +address JNI_FastGetField::generate_fast_get_int_field() { + return generate_fast_get_int_field0(T_INT); +} + +address JNI_FastGetField::generate_fast_get_long_field() { + // we don't have fast jni accessors. + return (address) -1; +} + +address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { + // e don't have fast jni accessors. + return (address) -1; +} + +address JNI_FastGetField::generate_fast_get_float_field() { + return generate_fast_get_float_field0(T_FLOAT); +} + +address JNI_FastGetField::generate_fast_get_double_field() { + return generate_fast_get_float_field0(T_DOUBLE); +} diff --git a/hotspot/src/cpu/ppc/vm/jniTypes_ppc.hpp b/hotspot/src/cpu/ppc/vm/jniTypes_ppc.hpp new file mode 100644 index 00000000000..9178bd442ad --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/jniTypes_ppc.hpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_JNITYPES_PPC_HPP +#define CPU_PPC_VM_JNITYPES_PPC_HPP + +#include "memory/allocation.hpp" +#include "oops/oop.hpp" +#include "prims/jni.h" + +// This file holds platform-dependent routines used to write primitive +// jni types to the array of arguments passed into JavaCalls::call. + +class JNITypes : AllStatic { + // These functions write a java primitive type (in native format) to + // a java stack slot array to be passed as an argument to + // JavaCalls:calls. I.e., they are functionally 'push' operations + // if they have a 'pos' formal parameter. Note that jlong's and + // jdouble's are written _in reverse_ of the order in which they + // appear in the interpreter stack. This is because call stubs (see + // stubGenerator_sparc.cpp) reverse the argument list constructed by + // JavaCallArguments (see javaCalls.hpp). + + private: + +#ifndef PPC64 +#error "ppc32 support currently not implemented!!!" +#endif // PPC64 + + public: + // Ints are stored in native format in one JavaCallArgument slot at *to. + static inline void put_int(jint from, intptr_t *to) { *(jint *)(to + 0 ) = from; } + static inline void put_int(jint from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = from; } + static inline void put_int(jint *from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = *from; } + + // Longs are stored in native format in one JavaCallArgument slot at + // *(to+1). + static inline void put_long(jlong from, intptr_t *to) { + *(jlong*) (to + 1) = from; + } + + static inline void put_long(jlong from, intptr_t *to, int& pos) { + *(jlong*) (to + 1 + pos) = from; + pos += 2; + } + + static inline void put_long(jlong *from, intptr_t *to, int& pos) { + *(jlong*) (to + 1 + pos) = *from; + pos += 2; + } + + // Oops are stored in native format in one JavaCallArgument slot at *to. + static inline void put_obj(oop from, intptr_t *to) { *(oop *)(to + 0 ) = from; } + static inline void put_obj(oop from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = from; } + static inline void put_obj(oop *from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = *from; } + + // Floats are stored in native format in one JavaCallArgument slot at *to. + static inline void put_float(jfloat from, intptr_t *to) { *(jfloat *)(to + 0 ) = from; } + static inline void put_float(jfloat from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = from; } + static inline void put_float(jfloat *from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = *from; } + + // Doubles are stored in native word format in one JavaCallArgument + // slot at *(to+1). + static inline void put_double(jdouble from, intptr_t *to) { + *(jdouble*) (to + 1) = from; + } + + static inline void put_double(jdouble from, intptr_t *to, int& pos) { + *(jdouble*) (to + 1 + pos) = from; + pos += 2; + } + + static inline void put_double(jdouble *from, intptr_t *to, int& pos) { + *(jdouble*) (to + 1 + pos) = *from; + pos += 2; + } + + // The get_xxx routines, on the other hand, actually _do_ fetch + // java primitive types from the interpreter stack. + // No need to worry about alignment on Intel. + static inline jint get_int (intptr_t *from) { return *(jint *) from; } + static inline jlong get_long (intptr_t *from) { return *(jlong *) (from + 1); } + static inline oop get_obj (intptr_t *from) { return *(oop *) from; } + static inline jfloat get_float (intptr_t *from) { return *(jfloat *) from; } + static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + 1); } +}; + +#endif // CPU_PPC_VM_JNITYPES_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/jni_ppc.h b/hotspot/src/cpu/ppc/vm/jni_ppc.h new file mode 100644 index 00000000000..e10dfd0583c --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/jni_ppc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef CPU_PPC_VM_JNI_PPC_H +#define CPU_PPC_VM_JNI_PPC_H + +// Note: please do not change these without also changing jni_md.h in the JDK +// repository +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) + #define JNIEXPORT __attribute__((visibility("default"))) + #define JNIIMPORT __attribute__((visibility("default"))) +#else + #define JNIEXPORT + #define JNIIMPORT +#endif + + #define JNICALL + typedef int jint; +#if defined(_LP64) + typedef long jlong; +#else + typedef long long jlong; +#endif + +typedef signed char jbyte; + +#endif // CPU_PPC_VM_JNI_PPC_H diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp new file mode 100644 index 00000000000..8567b1589b3 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -0,0 +1,3017 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "gc_interface/collectedHeap.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/cardTableModRefBS.hpp" +#include "memory/resourceArea.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" +#include "gc_implementation/g1/heapRegion.hpp" +#endif // INCLUDE_ALL_GCS + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) block_comment(str) +#endif + +#ifdef ASSERT +// On RISC, there's no benefit to verifying instruction boundaries. +bool AbstractAssembler::pd_check_instruction_mark() { return false; } +#endif + +void MacroAssembler::ld_largeoffset_unchecked(Register d, int si31, Register a, int emit_filler_nop) { + assert(Assembler::is_simm(si31, 31) && si31 >= 0, "si31 out of range"); + if (Assembler::is_simm(si31, 16)) { + ld(d, si31, a); + if (emit_filler_nop) nop(); + } else { + const int hi = MacroAssembler::largeoffset_si16_si16_hi(si31); + const int lo = MacroAssembler::largeoffset_si16_si16_lo(si31); + addis(d, a, hi); + ld(d, lo, d); + } +} + +void MacroAssembler::ld_largeoffset(Register d, int si31, Register a, int emit_filler_nop) { + assert_different_registers(d, a); + ld_largeoffset_unchecked(d, si31, a, emit_filler_nop); +} + +void MacroAssembler::load_sized_value(Register dst, RegisterOrConstant offs, Register base, + size_t size_in_bytes, bool is_signed) { + switch (size_in_bytes) { + case 8: ld(dst, offs, base); break; + case 4: is_signed ? lwa(dst, offs, base) : lwz(dst, offs, base); break; + case 2: is_signed ? lha(dst, offs, base) : lhz(dst, offs, base); break; + case 1: lbz(dst, offs, base); if (is_signed) extsb(dst, dst); break; // lba doesn't exist :( + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Register dst, RegisterOrConstant offs, Register base, + size_t size_in_bytes) { + switch (size_in_bytes) { + case 8: std(dst, offs, base); break; + case 4: stw(dst, offs, base); break; + case 2: sth(dst, offs, base); break; + case 1: stb(dst, offs, base); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::align(int modulus) { + while (offset() % modulus != 0) nop(); +} + +// Issue instructions that calculate given TOC from global TOC. +void MacroAssembler::calculate_address_from_global_toc(Register dst, address addr, bool hi16, bool lo16, + bool add_relocation, bool emit_dummy_addr) { + int offset = -1; + if (emit_dummy_addr) { + offset = -128; // dummy address + } else if (addr != (address)(intptr_t)-1) { + offset = MacroAssembler::offset_to_global_toc(addr); + } + + if (hi16) { + addis(dst, R29, MacroAssembler::largeoffset_si16_si16_hi(offset)); + } + if (lo16) { + if (add_relocation) { + // Relocate at the addi to avoid confusion with a load from the method's TOC. + relocate(internal_word_Relocation::spec(addr)); + } + addi(dst, dst, MacroAssembler::largeoffset_si16_si16_lo(offset)); + } +} + +int MacroAssembler::patch_calculate_address_from_global_toc_at(address a, address bound, address addr) { + const int offset = MacroAssembler::offset_to_global_toc(addr); + + const address inst2_addr = a; + const int inst2 = *(int *)inst2_addr; + + // The relocation points to the second instruction, the addi, + // and the addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + + // Now, find the preceding addis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + while (inst1_addr >= bound) { + inst1 = *(int *) inst1_addr; + if (is_addis(inst1) && inv_rt_field(inst1) == dst) { + // Stop, found the addis which writes dst. + break; + } + inst1_addr -= BytesPerInstWord; + } + + assert(is_addis(inst1) && inv_ra_field(inst1) == 29 /* R29 */, "source must be global TOC"); + set_imm((int *)inst1_addr, MacroAssembler::largeoffset_si16_si16_hi(offset)); + set_imm((int *)inst2_addr, MacroAssembler::largeoffset_si16_si16_lo(offset)); + return (int)((intptr_t)addr - (intptr_t)inst1_addr); +} + +address MacroAssembler::get_address_of_calculate_address_from_global_toc_at(address a, address bound) { + const address inst2_addr = a; + const int inst2 = *(int *)inst2_addr; + + // The relocation points to the second instruction, the addi, + // and the addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + + // Now, find the preceding addis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + while (inst1_addr >= bound) { + inst1 = *(int *) inst1_addr; + if (is_addis(inst1) && inv_rt_field(inst1) == dst) { + // stop, found the addis which writes dst + break; + } + inst1_addr -= BytesPerInstWord; + } + + assert(is_addis(inst1) && inv_ra_field(inst1) == 29 /* R29 */, "source must be global TOC"); + + int offset = (get_imm(inst1_addr, 0) << 16) + get_imm(inst2_addr, 0); + // -1 is a special case + if (offset == -1) { + return (address)(intptr_t)-1; + } else { + return global_toc() + offset; + } +} + +#ifdef _LP64 +// Patch compressed oops or klass constants. +int MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop data) { + assert(UseCompressedOops, "Should only patch compressed oops"); + + const address inst2_addr = a; + const int inst2 = *(int *)inst2_addr; + + // The relocation points to the second instruction, the addi, + // and the addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + // Now, find the preceding addis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + bool inst1_found = false; + while (inst1_addr >= bound) { + inst1 = *(int *)inst1_addr; + if (is_lis(inst1) && inv_rs_field(inst1) == dst) { inst1_found = true; break; } + inst1_addr -= BytesPerInstWord; + } + assert(inst1_found, "inst is not lis"); + + int xc = (data >> 16) & 0xffff; + int xd = (data >> 0) & 0xffff; + + set_imm((int *)inst1_addr,((short)(xc + ((xd & 0x8000) != 0 ? 1 : 0)))); // see enc_load_con_narrow1/2 + set_imm((int *)inst2_addr, (short)(xd)); + return (int)((intptr_t)inst2_addr - (intptr_t)inst1_addr); +} + +// Get compressed oop or klass constant. +narrowOop MacroAssembler::get_narrow_oop(address a, address bound) { + assert(UseCompressedOops, "Should only patch compressed oops"); + + const address inst2_addr = a; + const int inst2 = *(int *)inst2_addr; + + // The relocation points to the second instruction, the addi, + // and the addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + // Now, find the preceding lis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + bool inst1_found = false; + + while (inst1_addr >= bound) { + inst1 = *(int *) inst1_addr; + if (is_lis(inst1) && inv_rs_field(inst1) == dst) { inst1_found = true; break;} + inst1_addr -= BytesPerInstWord; + } + assert(inst1_found, "inst is not lis"); + + uint xl = ((unsigned int) (get_imm(inst2_addr,0) & 0xffff)); + uint xh = (((((xl & 0x8000) != 0 ? -1 : 0) + get_imm(inst1_addr,0)) & 0xffff) << 16); + return (int) (xl | xh); +} +#endif // _LP64 + +void MacroAssembler::load_const_from_method_toc(Register dst, AddressLiteral& a, Register toc) { + int toc_offset = 0; + // Use RelocationHolder::none for the constant pool entry, otherwise + // we will end up with a failing NativeCall::verify(x) where x is + // the address of the constant pool entry. + // FIXME: We should insert relocation information for oops at the constant + // pool entries instead of inserting it at the loads; patching of a constant + // pool entry should be less expensive. + Unimplemented(); + if (false) { + address oop_address = address_constant((address)a.value(), RelocationHolder::none); + // Relocate at the pc of the load. + relocate(a.rspec()); + toc_offset = (int)(oop_address - code()->consts()->start()); + } + ld_largeoffset_unchecked(dst, toc_offset, toc, true); +} + +bool MacroAssembler::is_load_const_from_method_toc_at(address a) { + const address inst1_addr = a; + const int inst1 = *(int *)inst1_addr; + + // The relocation points to the ld or the addis. + return (is_ld(inst1)) || + (is_addis(inst1) && inv_ra_field(inst1) != 0); +} + +int MacroAssembler::get_offset_of_load_const_from_method_toc_at(address a) { + assert(is_load_const_from_method_toc_at(a), "must be load_const_from_method_toc"); + + const address inst1_addr = a; + const int inst1 = *(int *)inst1_addr; + + if (is_ld(inst1)) { + return inv_d1_field(inst1); + } else if (is_addis(inst1)) { + const int dst = inv_rt_field(inst1); + + // Now, find the succeeding ld which reads and writes to dst. + address inst2_addr = inst1_addr + BytesPerInstWord; + int inst2 = 0; + while (true) { + inst2 = *(int *) inst2_addr; + if (is_ld(inst2) && inv_ra_field(inst2) == dst && inv_rt_field(inst2) == dst) { + // Stop, found the ld which reads and writes dst. + break; + } + inst2_addr += BytesPerInstWord; + } + return (inv_d1_field(inst1) << 16) + inv_d1_field(inst2); + } + ShouldNotReachHere(); + return 0; +} + +// Get the constant from a `load_const' sequence. +long MacroAssembler::get_const(address a) { + assert(is_load_const_at(a), "not a load of a constant"); + const int *p = (const int*) a; + unsigned long x = (((unsigned long) (get_imm(a,0) & 0xffff)) << 48); + if (is_ori(*(p+1))) { + x |= (((unsigned long) (get_imm(a,1) & 0xffff)) << 32); + x |= (((unsigned long) (get_imm(a,3) & 0xffff)) << 16); + x |= (((unsigned long) (get_imm(a,4) & 0xffff))); + } else if (is_lis(*(p+1))) { + x |= (((unsigned long) (get_imm(a,2) & 0xffff)) << 32); + x |= (((unsigned long) (get_imm(a,1) & 0xffff)) << 16); + x |= (((unsigned long) (get_imm(a,3) & 0xffff))); + } else { + ShouldNotReachHere(); + return (long) 0; + } + return (long) x; +} + +// Patch the 64 bit constant of a `load_const' sequence. This is a low +// level procedure. It neither flushes the instruction cache nor is it +// mt safe. +void MacroAssembler::patch_const(address a, long x) { + assert(is_load_const_at(a), "not a load of a constant"); + int *p = (int*) a; + if (is_ori(*(p+1))) { + set_imm(0 + p, (x >> 48) & 0xffff); + set_imm(1 + p, (x >> 32) & 0xffff); + set_imm(3 + p, (x >> 16) & 0xffff); + set_imm(4 + p, x & 0xffff); + } else if (is_lis(*(p+1))) { + set_imm(0 + p, (x >> 48) & 0xffff); + set_imm(2 + p, (x >> 32) & 0xffff); + set_imm(1 + p, (x >> 16) & 0xffff); + set_imm(3 + p, x & 0xffff); + } else { + ShouldNotReachHere(); + } +} + +AddressLiteral MacroAssembler::allocate_metadata_address(Metadata* obj) { + assert(oop_recorder() != NULL, "this assembler needs a Recorder"); + int index = oop_recorder()->allocate_metadata_index(obj); + RelocationHolder rspec = metadata_Relocation::spec(index); + return AddressLiteral((address)obj, rspec); +} + +AddressLiteral MacroAssembler::constant_metadata_address(Metadata* obj) { + assert(oop_recorder() != NULL, "this assembler needs a Recorder"); + int index = oop_recorder()->find_index(obj); + RelocationHolder rspec = metadata_Relocation::spec(index); + return AddressLiteral((address)obj, rspec); +} + +AddressLiteral MacroAssembler::allocate_oop_address(jobject obj) { + assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->allocate_oop_index(obj); + return AddressLiteral(address(obj), oop_Relocation::spec(oop_index)); +} + +AddressLiteral MacroAssembler::constant_oop_address(jobject obj) { + assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + return AddressLiteral(address(obj), oop_Relocation::spec(oop_index)); +} + +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, int offset) { + intptr_t value = *delayed_value_addr; + if (value != 0) { + return RegisterOrConstant(value + offset); + } + + // Load indirectly to solve generation ordering problem. + // static address, no relocation + int simm16_offset = load_const_optimized(tmp, delayed_value_addr, noreg, true); + ld(tmp, simm16_offset, tmp); // must be aligned ((xa & 3) == 0) + + if (offset != 0) { + addi(tmp, tmp, offset); + } + + return RegisterOrConstant(tmp); +} + +#ifndef PRODUCT +void MacroAssembler::pd_print_patched_instruction(address branch) { + Unimplemented(); // TODO: PPC port +} +#endif // ndef PRODUCT + +// Conditional far branch for destinations encodable in 24+2 bits. +void MacroAssembler::bc_far(int boint, int biint, Label& dest, int optimize) { + + // If requested by flag optimize, relocate the bc_far as a + // runtime_call and prepare for optimizing it when the code gets + // relocated. + if (optimize == bc_far_optimize_on_relocate) { + relocate(relocInfo::runtime_call_type); + } + + // variant 2: + // + // b!cxx SKIP + // bxx DEST + // SKIP: + // + + const int opposite_boint = add_bhint_to_boint(opposite_bhint(inv_boint_bhint(boint)), + opposite_bcond(inv_boint_bcond(boint))); + + // We emit two branches. + // First, a conditional branch which jumps around the far branch. + const address not_taken_pc = pc() + 2 * BytesPerInstWord; + const address bc_pc = pc(); + bc(opposite_boint, biint, not_taken_pc); + + const int bc_instr = *(int*)bc_pc; + assert(not_taken_pc == (address)inv_bd_field(bc_instr, (intptr_t)bc_pc), "postcondition"); + assert(opposite_boint == inv_bo_field(bc_instr), "postcondition"); + assert(boint == add_bhint_to_boint(opposite_bhint(inv_boint_bhint(inv_bo_field(bc_instr))), + opposite_bcond(inv_boint_bcond(inv_bo_field(bc_instr)))), + "postcondition"); + assert(biint == inv_bi_field(bc_instr), "postcondition"); + + // Second, an unconditional far branch which jumps to dest. + // Note: target(dest) remembers the current pc (see CodeSection::target) + // and returns the current pc if the label is not bound yet; when + // the label gets bound, the unconditional far branch will be patched. + const address target_pc = target(dest); + const address b_pc = pc(); + b(target_pc); + + assert(not_taken_pc == pc(), "postcondition"); + assert(dest.is_bound() || target_pc == b_pc, "postcondition"); +} + +bool MacroAssembler::is_bc_far_at(address instruction_addr) { + return is_bc_far_variant1_at(instruction_addr) || + is_bc_far_variant2_at(instruction_addr) || + is_bc_far_variant3_at(instruction_addr); +} + +address MacroAssembler::get_dest_of_bc_far_at(address instruction_addr) { + if (is_bc_far_variant1_at(instruction_addr)) { + const address instruction_1_addr = instruction_addr; + const int instruction_1 = *(int*)instruction_1_addr; + return (address)inv_bd_field(instruction_1, (intptr_t)instruction_1_addr); + } else if (is_bc_far_variant2_at(instruction_addr)) { + const address instruction_2_addr = instruction_addr + 4; + return bxx_destination(instruction_2_addr); + } else if (is_bc_far_variant3_at(instruction_addr)) { + return instruction_addr + 8; + } + // variant 4 ??? + ShouldNotReachHere(); + return NULL; +} +void MacroAssembler::set_dest_of_bc_far_at(address instruction_addr, address dest) { + + if (is_bc_far_variant3_at(instruction_addr)) { + // variant 3, far cond branch to the next instruction, already patched to nops: + // + // nop + // endgroup + // SKIP/DEST: + // + return; + } + + // first, extract boint and biint from the current branch + int boint = 0; + int biint = 0; + + ResourceMark rm; + const int code_size = 2 * BytesPerInstWord; + CodeBuffer buf(instruction_addr, code_size); + MacroAssembler masm(&buf); + if (is_bc_far_variant2_at(instruction_addr) && dest == instruction_addr + 8) { + // Far branch to next instruction: Optimize it by patching nops (produce variant 3). + masm.nop(); + masm.endgroup(); + } else { + if (is_bc_far_variant1_at(instruction_addr)) { + // variant 1, the 1st instruction contains the destination address: + // + // bcxx DEST + // endgroup + // + const int instruction_1 = *(int*)(instruction_addr); + boint = inv_bo_field(instruction_1); + biint = inv_bi_field(instruction_1); + } else if (is_bc_far_variant2_at(instruction_addr)) { + // variant 2, the 2nd instruction contains the destination address: + // + // b!cxx SKIP + // bxx DEST + // SKIP: + // + const int instruction_1 = *(int*)(instruction_addr); + boint = add_bhint_to_boint(opposite_bhint(inv_boint_bhint(inv_bo_field(instruction_1))), + opposite_bcond(inv_boint_bcond(inv_bo_field(instruction_1)))); + biint = inv_bi_field(instruction_1); + } else { + // variant 4??? + ShouldNotReachHere(); + } + + // second, set the new branch destination and optimize the code + if (dest != instruction_addr + 4 && // the bc_far is still unbound! + masm.is_within_range_of_bcxx(dest, instruction_addr)) { + // variant 1: + // + // bcxx DEST + // endgroup + // + masm.bc(boint, biint, dest); + masm.endgroup(); + } else { + // variant 2: + // + // b!cxx SKIP + // bxx DEST + // SKIP: + // + const int opposite_boint = add_bhint_to_boint(opposite_bhint(inv_boint_bhint(boint)), + opposite_bcond(inv_boint_bcond(boint))); + const address not_taken_pc = masm.pc() + 2 * BytesPerInstWord; + masm.bc(opposite_boint, biint, not_taken_pc); + masm.b(dest); + } + } + ICache::invalidate_range(instruction_addr, code_size); +} + +// Emit a NOT mt-safe patchable 64 bit absolute call/jump. +void MacroAssembler::bxx64_patchable(address dest, relocInfo::relocType rt, bool link) { + // get current pc + uint64_t start_pc = (uint64_t) pc(); + + const address pc_of_bl = (address) (start_pc + (6*BytesPerInstWord)); // bl is last + const address pc_of_b = (address) (start_pc + (0*BytesPerInstWord)); // b is first + + // relocate here + if (rt != relocInfo::none) { + relocate(rt); + } + + if ( ReoptimizeCallSequences && + (( link && is_within_range_of_b(dest, pc_of_bl)) || + (!link && is_within_range_of_b(dest, pc_of_b)))) { + // variant 2: + // Emit an optimized, pc-relative call/jump. + + if (link) { + // some padding + nop(); + nop(); + nop(); + nop(); + nop(); + nop(); + + // do the call + assert(pc() == pc_of_bl, "just checking"); + bl(dest, relocInfo::none); + } else { + // do the jump + assert(pc() == pc_of_b, "just checking"); + b(dest, relocInfo::none); + + // some padding + nop(); + nop(); + nop(); + nop(); + nop(); + nop(); + } + + // Assert that we can identify the emitted call/jump. + assert(is_bxx64_patchable_variant2_at((address)start_pc, link), + "can't identify emitted call"); + } else { + // variant 1: + + mr(R0, R11); // spill R11 -> R0. + + // Load the destination address into CTR, + // calculate destination relative to global toc. + calculate_address_from_global_toc(R11, dest, true, true, false); + + mtctr(R11); + mr(R11, R0); // spill R11 <- R0. + nop(); + + // do the call/jump + if (link) { + bctrl(); + } else{ + bctr(); + } + // Assert that we can identify the emitted call/jump. + assert(is_bxx64_patchable_variant1b_at((address)start_pc, link), + "can't identify emitted call"); + } + + // Assert that we can identify the emitted call/jump. + assert(is_bxx64_patchable_at((address)start_pc, link), + "can't identify emitted call"); + assert(get_dest_of_bxx64_patchable_at((address)start_pc, link) == dest, + "wrong encoding of dest address"); +} + +// Identify a bxx64_patchable instruction. +bool MacroAssembler::is_bxx64_patchable_at(address instruction_addr, bool link) { + return is_bxx64_patchable_variant1b_at(instruction_addr, link) + //|| is_bxx64_patchable_variant1_at(instruction_addr, link) + || is_bxx64_patchable_variant2_at(instruction_addr, link); +} + +// Does the call64_patchable instruction use a pc-relative encoding of +// the call destination? +bool MacroAssembler::is_bxx64_patchable_pcrelative_at(address instruction_addr, bool link) { + // variant 2 is pc-relative + return is_bxx64_patchable_variant2_at(instruction_addr, link); +} + +// Identify variant 1. +bool MacroAssembler::is_bxx64_patchable_variant1_at(address instruction_addr, bool link) { + unsigned int* instr = (unsigned int*) instruction_addr; + return (link ? is_bctrl(instr[6]) : is_bctr(instr[6])) // bctr[l] + && is_mtctr(instr[5]) // mtctr + && is_load_const_at(instruction_addr); +} + +// Identify variant 1b: load destination relative to global toc. +bool MacroAssembler::is_bxx64_patchable_variant1b_at(address instruction_addr, bool link) { + unsigned int* instr = (unsigned int*) instruction_addr; + return (link ? is_bctrl(instr[6]) : is_bctr(instr[6])) // bctr[l] + && is_mtctr(instr[3]) // mtctr + && is_calculate_address_from_global_toc_at(instruction_addr + 2*BytesPerInstWord, instruction_addr); +} + +// Identify variant 2. +bool MacroAssembler::is_bxx64_patchable_variant2_at(address instruction_addr, bool link) { + unsigned int* instr = (unsigned int*) instruction_addr; + if (link) { + return is_bl (instr[6]) // bl dest is last + && is_nop(instr[0]) // nop + && is_nop(instr[1]) // nop + && is_nop(instr[2]) // nop + && is_nop(instr[3]) // nop + && is_nop(instr[4]) // nop + && is_nop(instr[5]); // nop + } else { + return is_b (instr[0]) // b dest is first + && is_nop(instr[1]) // nop + && is_nop(instr[2]) // nop + && is_nop(instr[3]) // nop + && is_nop(instr[4]) // nop + && is_nop(instr[5]) // nop + && is_nop(instr[6]); // nop + } +} + +// Set dest address of a bxx64_patchable instruction. +void MacroAssembler::set_dest_of_bxx64_patchable_at(address instruction_addr, address dest, bool link) { + ResourceMark rm; + int code_size = MacroAssembler::bxx64_patchable_size; + CodeBuffer buf(instruction_addr, code_size); + MacroAssembler masm(&buf); + masm.bxx64_patchable(dest, relocInfo::none, link); + ICache::invalidate_range(instruction_addr, code_size); +} + +// Get dest address of a bxx64_patchable instruction. +address MacroAssembler::get_dest_of_bxx64_patchable_at(address instruction_addr, bool link) { + if (is_bxx64_patchable_variant1_at(instruction_addr, link)) { + return (address) (unsigned long) get_const(instruction_addr); + } else if (is_bxx64_patchable_variant2_at(instruction_addr, link)) { + unsigned int* instr = (unsigned int*) instruction_addr; + if (link) { + const int instr_idx = 6; // bl is last + int branchoffset = branch_destination(instr[instr_idx], 0); + return instruction_addr + branchoffset + instr_idx*BytesPerInstWord; + } else { + const int instr_idx = 0; // b is first + int branchoffset = branch_destination(instr[instr_idx], 0); + return instruction_addr + branchoffset + instr_idx*BytesPerInstWord; + } + // Load dest relative to global toc. + } else if (is_bxx64_patchable_variant1b_at(instruction_addr, link)) { + return get_address_of_calculate_address_from_global_toc_at(instruction_addr + 2*BytesPerInstWord, + instruction_addr); + } else { + ShouldNotReachHere(); + return NULL; + } +} + +// Uses ordering which corresponds to ABI: +// _savegpr0_14: std r14,-144(r1) +// _savegpr0_15: std r15,-136(r1) +// _savegpr0_16: std r16,-128(r1) +void MacroAssembler::save_nonvolatile_gprs(Register dst, int offset) { + std(R14, offset, dst); offset += 8; + std(R15, offset, dst); offset += 8; + std(R16, offset, dst); offset += 8; + std(R17, offset, dst); offset += 8; + std(R18, offset, dst); offset += 8; + std(R19, offset, dst); offset += 8; + std(R20, offset, dst); offset += 8; + std(R21, offset, dst); offset += 8; + std(R22, offset, dst); offset += 8; + std(R23, offset, dst); offset += 8; + std(R24, offset, dst); offset += 8; + std(R25, offset, dst); offset += 8; + std(R26, offset, dst); offset += 8; + std(R27, offset, dst); offset += 8; + std(R28, offset, dst); offset += 8; + std(R29, offset, dst); offset += 8; + std(R30, offset, dst); offset += 8; + std(R31, offset, dst); offset += 8; + + stfd(F14, offset, dst); offset += 8; + stfd(F15, offset, dst); offset += 8; + stfd(F16, offset, dst); offset += 8; + stfd(F17, offset, dst); offset += 8; + stfd(F18, offset, dst); offset += 8; + stfd(F19, offset, dst); offset += 8; + stfd(F20, offset, dst); offset += 8; + stfd(F21, offset, dst); offset += 8; + stfd(F22, offset, dst); offset += 8; + stfd(F23, offset, dst); offset += 8; + stfd(F24, offset, dst); offset += 8; + stfd(F25, offset, dst); offset += 8; + stfd(F26, offset, dst); offset += 8; + stfd(F27, offset, dst); offset += 8; + stfd(F28, offset, dst); offset += 8; + stfd(F29, offset, dst); offset += 8; + stfd(F30, offset, dst); offset += 8; + stfd(F31, offset, dst); +} + +// Uses ordering which corresponds to ABI: +// _restgpr0_14: ld r14,-144(r1) +// _restgpr0_15: ld r15,-136(r1) +// _restgpr0_16: ld r16,-128(r1) +void MacroAssembler::restore_nonvolatile_gprs(Register src, int offset) { + ld(R14, offset, src); offset += 8; + ld(R15, offset, src); offset += 8; + ld(R16, offset, src); offset += 8; + ld(R17, offset, src); offset += 8; + ld(R18, offset, src); offset += 8; + ld(R19, offset, src); offset += 8; + ld(R20, offset, src); offset += 8; + ld(R21, offset, src); offset += 8; + ld(R22, offset, src); offset += 8; + ld(R23, offset, src); offset += 8; + ld(R24, offset, src); offset += 8; + ld(R25, offset, src); offset += 8; + ld(R26, offset, src); offset += 8; + ld(R27, offset, src); offset += 8; + ld(R28, offset, src); offset += 8; + ld(R29, offset, src); offset += 8; + ld(R30, offset, src); offset += 8; + ld(R31, offset, src); offset += 8; + + // FP registers + lfd(F14, offset, src); offset += 8; + lfd(F15, offset, src); offset += 8; + lfd(F16, offset, src); offset += 8; + lfd(F17, offset, src); offset += 8; + lfd(F18, offset, src); offset += 8; + lfd(F19, offset, src); offset += 8; + lfd(F20, offset, src); offset += 8; + lfd(F21, offset, src); offset += 8; + lfd(F22, offset, src); offset += 8; + lfd(F23, offset, src); offset += 8; + lfd(F24, offset, src); offset += 8; + lfd(F25, offset, src); offset += 8; + lfd(F26, offset, src); offset += 8; + lfd(F27, offset, src); offset += 8; + lfd(F28, offset, src); offset += 8; + lfd(F29, offset, src); offset += 8; + lfd(F30, offset, src); offset += 8; + lfd(F31, offset, src); +} + +// For verify_oops. +void MacroAssembler::save_volatile_gprs(Register dst, int offset) { + std(R3, offset, dst); offset += 8; + std(R4, offset, dst); offset += 8; + std(R5, offset, dst); offset += 8; + std(R6, offset, dst); offset += 8; + std(R7, offset, dst); offset += 8; + std(R8, offset, dst); offset += 8; + std(R9, offset, dst); offset += 8; + std(R10, offset, dst); offset += 8; + std(R11, offset, dst); offset += 8; + std(R12, offset, dst); +} + +// For verify_oops. +void MacroAssembler::restore_volatile_gprs(Register src, int offset) { + ld(R3, offset, src); offset += 8; + ld(R4, offset, src); offset += 8; + ld(R5, offset, src); offset += 8; + ld(R6, offset, src); offset += 8; + ld(R7, offset, src); offset += 8; + ld(R8, offset, src); offset += 8; + ld(R9, offset, src); offset += 8; + ld(R10, offset, src); offset += 8; + ld(R11, offset, src); offset += 8; + ld(R12, offset, src); +} + +void MacroAssembler::save_LR_CR(Register tmp) { + mfcr(tmp); + std(tmp, _abi(cr), R1_SP); + mflr(tmp); + std(tmp, _abi(lr), R1_SP); + // Tmp must contain lr on exit! (see return_addr and prolog in ppc64.ad) +} + +void MacroAssembler::restore_LR_CR(Register tmp) { + assert(tmp != R1_SP, "must be distinct"); + ld(tmp, _abi(lr), R1_SP); + mtlr(tmp); + ld(tmp, _abi(cr), R1_SP); + mtcr(tmp); +} + +address MacroAssembler::get_PC_trash_LR(Register result) { + Label L; + bl(L); + bind(L); + address lr_pc = pc(); + mflr(result); + return lr_pc; +} + +void MacroAssembler::resize_frame(Register offset, Register tmp) { +#ifdef ASSERT + assert_different_registers(offset, tmp, R1_SP); + andi_(tmp, offset, frame::alignment_in_bytes-1); + asm_assert_eq("resize_frame: unaligned", 0x204); +#endif + + // tmp <- *(SP) + ld(tmp, _abi(callers_sp), R1_SP); + // addr <- SP + offset; + // *(addr) <- tmp; + // SP <- addr + stdux(tmp, R1_SP, offset); +} + +void MacroAssembler::resize_frame(int offset, Register tmp) { + assert(is_simm(offset, 16), "too big an offset"); + assert_different_registers(tmp, R1_SP); + assert((offset & (frame::alignment_in_bytes-1))==0, "resize_frame: unaligned"); + // tmp <- *(SP) + ld(tmp, _abi(callers_sp), R1_SP); + // addr <- SP + offset; + // *(addr) <- tmp; + // SP <- addr + stdu(tmp, offset, R1_SP); +} + +void MacroAssembler::resize_frame_absolute(Register addr, Register tmp1, Register tmp2) { + // (addr == tmp1) || (addr == tmp2) is allowed here! + assert(tmp1 != tmp2, "must be distinct"); + + // compute offset w.r.t. current stack pointer + // tmp_1 <- addr - SP (!) + subf(tmp1, R1_SP, addr); + + // atomically update SP keeping back link. + resize_frame(tmp1/* offset */, tmp2/* tmp */); +} + +void MacroAssembler::push_frame(Register bytes, Register tmp) { +#ifdef ASSERT + assert(bytes != R0, "r0 not allowed here"); + andi_(R0, bytes, frame::alignment_in_bytes-1); + asm_assert_eq("push_frame(Reg, Reg): unaligned", 0x203); +#endif + neg(tmp, bytes); + stdux(R1_SP, R1_SP, tmp); +} + +// Push a frame of size `bytes'. +void MacroAssembler::push_frame(unsigned int bytes, Register tmp) { + long offset = align_addr(bytes, frame::alignment_in_bytes); + if (is_simm(-offset, 16)) { + stdu(R1_SP, -offset, R1_SP); + } else { + load_const(tmp, -offset); + stdux(R1_SP, R1_SP, tmp); + } +} + +// Push a frame of size `bytes' plus abi112 on top. +void MacroAssembler::push_frame_abi112(unsigned int bytes, Register tmp) { + push_frame(bytes + frame::abi_112_size, tmp); +} + +// Setup up a new C frame with a spill area for non-volatile GPRs and +// additional space for local variables. +void MacroAssembler::push_frame_abi112_nonvolatiles(unsigned int bytes, + Register tmp) { + push_frame(bytes + frame::abi_112_size + frame::spill_nonvolatiles_size, tmp); +} + +// Pop current C frame. +void MacroAssembler::pop_frame() { + ld(R1_SP, _abi(callers_sp), R1_SP); +} + +// Generic version of a call to C function via a function descriptor +// with variable support for C calling conventions (TOC, ENV, etc.). +// Updates and returns _last_calls_return_pc. +address MacroAssembler::branch_to(Register function_descriptor, bool and_link, bool save_toc_before_call, + bool restore_toc_after_call, bool load_toc_of_callee, bool load_env_of_callee) { + // we emit standard ptrgl glue code here + assert((function_descriptor != R0), "function_descriptor cannot be R0"); + + // retrieve necessary entries from the function descriptor + ld(R0, in_bytes(FunctionDescriptor::entry_offset()), function_descriptor); + mtctr(R0); + + if (load_toc_of_callee) { + ld(R2_TOC, in_bytes(FunctionDescriptor::toc_offset()), function_descriptor); + } + if (load_env_of_callee) { + ld(R11, in_bytes(FunctionDescriptor::env_offset()), function_descriptor); + } else if (load_toc_of_callee) { + li(R11, 0); + } + + // do a call or a branch + if (and_link) { + bctrl(); + } else { + bctr(); + } + _last_calls_return_pc = pc(); + + return _last_calls_return_pc; +} + +// Call a C function via a function descriptor and use full C calling +// conventions. +// We don't use the TOC in generated code, so there is no need to save +// and restore its value. +address MacroAssembler::call_c(Register fd) { + return branch_to(fd, /*and_link=*/true, + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/true); +} + +address MacroAssembler::call_c(const FunctionDescriptor* fd, relocInfo::relocType rt) { + if (rt != relocInfo::none) { + // this call needs to be relocatable + if (!ReoptimizeCallSequences + || (rt != relocInfo::runtime_call_type && rt != relocInfo::none) + || fd == NULL // support code-size estimation + || !fd->is_friend_function() + || fd->entry() == NULL) { + // it's not a friend function as defined by class FunctionDescriptor, + // so do a full call-c here. + load_const(R11, (address)fd, R0); + + bool has_env = (fd != NULL && fd->env() != NULL); + return branch_to(R11, /*and_link=*/true, + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/has_env); + } else { + // It's a friend function. Load the entry point and don't care about + // toc and env. Use an optimizable call instruction, but ensure the + // same code-size as in the case of a non-friend function. + nop(); + nop(); + nop(); + bl64_patchable(fd->entry(), rt); + _last_calls_return_pc = pc(); + return _last_calls_return_pc; + } + } else { + // This call does not need to be relocatable, do more aggressive + // optimizations. + if (!ReoptimizeCallSequences + || !fd->is_friend_function()) { + // It's not a friend function as defined by class FunctionDescriptor, + // so do a full call-c here. + load_const(R11, (address)fd, R0); + return branch_to(R11, /*and_link=*/true, + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/true); + } else { + // it's a friend function, load the entry point and don't care about + // toc and env. + address dest = fd->entry(); + if (is_within_range_of_b(dest, pc())) { + bl(dest); + } else { + bl64_patchable(dest, rt); + } + _last_calls_return_pc = pc(); + return _last_calls_return_pc; + } + } +} + +// Call a C function. All constants needed reside in TOC. +// +// Read the address to call from the TOC. +// Read env from TOC, if fd specifies an env. +// Read new TOC from TOC. +address MacroAssembler::call_c_using_toc(const FunctionDescriptor* fd, + relocInfo::relocType rt, Register toc) { + if (!ReoptimizeCallSequences + || (rt != relocInfo::runtime_call_type && rt != relocInfo::none) + || !fd->is_friend_function()) { + // It's not a friend function as defined by class FunctionDescriptor, + // so do a full call-c here. + assert(fd->entry() != NULL, "function must be linked"); + + AddressLiteral fd_entry(fd->entry()); + load_const_from_method_toc(R11, fd_entry, toc); + mtctr(R11); + if (fd->env() == NULL) { + li(R11, 0); + nop(); + } else { + AddressLiteral fd_env(fd->env()); + load_const_from_method_toc(R11, fd_env, toc); + } + AddressLiteral fd_toc(fd->toc()); + load_toc_from_toc(R2_TOC, fd_toc, toc); + // R2_TOC is killed. + bctrl(); + _last_calls_return_pc = pc(); + } else { + // It's a friend function, load the entry point and don't care about + // toc and env. Use an optimizable call instruction, but ensure the + // same code-size as in the case of a non-friend function. + nop(); + bl64_patchable(fd->entry(), rt); + _last_calls_return_pc = pc(); + } + return _last_calls_return_pc; +} + +void MacroAssembler::call_VM_base(Register oop_result, + Register last_java_sp, + address entry_point, + bool check_exceptions) { + BLOCK_COMMENT("call_VM {"); + // Determine last_java_sp register. + if (!last_java_sp->is_valid()) { + last_java_sp = R1_SP; + } + set_top_ijava_frame_at_SP_as_last_Java_frame(last_java_sp, R11_scratch1); + + // ARG1 must hold thread address. + mr(R3_ARG1, R16_thread); + + address return_pc = call_c((FunctionDescriptor*)entry_point, relocInfo::none); + + reset_last_Java_frame(); + + // Check for pending exceptions. + if (check_exceptions) { + // We don't check for exceptions here. + ShouldNotReachHere(); + } + + // Get oop result if there is one and reset the value in the thread. + if (oop_result->is_valid()) { + get_vm_result(oop_result); + } + + _last_calls_return_pc = return_pc; + BLOCK_COMMENT("} call_VM"); +} + +void MacroAssembler::call_VM_leaf_base(address entry_point) { + BLOCK_COMMENT("call_VM_leaf {"); + call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, entry_point), relocInfo::none); + BLOCK_COMMENT("} call_VM_leaf"); +} + +void MacroAssembler::call_VM(Register oop_result, address entry_point, bool check_exceptions) { + call_VM_base(oop_result, noreg, entry_point, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, + bool check_exceptions) { + // R3_ARG1 is reserved for the thread. + mr_if_needed(R4_ARG2, arg_1); + call_VM(oop_result, entry_point, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, + bool check_exceptions) { + // R3_ARG1 is reserved for the thread + mr_if_needed(R4_ARG2, arg_1); + assert(arg_2 != R4_ARG2, "smashed argument"); + mr_if_needed(R5_ARG3, arg_2); + call_VM(oop_result, entry_point, check_exceptions); +} + +void MacroAssembler::call_VM_leaf(address entry_point) { + call_VM_leaf_base(entry_point); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1) { + mr_if_needed(R3_ARG1, arg_1); + call_VM_leaf(entry_point); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { + mr_if_needed(R3_ARG1, arg_1); + assert(arg_2 != R3_ARG1, "smashed argument"); + mr_if_needed(R4_ARG2, arg_2); + call_VM_leaf(entry_point); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { + mr_if_needed(R3_ARG1, arg_1); + assert(arg_2 != R3_ARG1, "smashed argument"); + mr_if_needed(R4_ARG2, arg_2); + assert(arg_3 != R3_ARG1 && arg_3 != R4_ARG2, "smashed argument"); + mr_if_needed(R5_ARG3, arg_3); + call_VM_leaf(entry_point); +} + +// Check whether instruction is a read access to the polling page +// which was emitted by load_from_polling_page(..). +bool MacroAssembler::is_load_from_polling_page(int instruction, void* ucontext, + address* polling_address_ptr) { + if (!is_ld(instruction)) + return false; // It's not a ld. Fail. + + int rt = inv_rt_field(instruction); + int ra = inv_ra_field(instruction); + int ds = inv_ds_field(instruction); + if (!(ds == 0 && ra != 0 && rt == 0)) { + return false; // It's not a ld(r0, X, ra). Fail. + } + + if (!ucontext) { + // Set polling address. + if (polling_address_ptr != NULL) { + *polling_address_ptr = NULL; + } + return true; // No ucontext given. Can't check value of ra. Assume true. + } + +#ifdef LINUX + // Ucontext given. Check that register ra contains the address of + // the safepoing polling page. + ucontext_t* uc = (ucontext_t*) ucontext; + // Set polling address. + address addr = (address)uc->uc_mcontext.regs->gpr[ra] + (ssize_t)ds; + if (polling_address_ptr != NULL) { + *polling_address_ptr = addr; + } + return os::is_poll_address(addr); +#else + // Not on Linux, ucontext must be NULL. + ShouldNotReachHere(); + return false; +#endif +} + +bool MacroAssembler::is_memory_serialization(int instruction, JavaThread* thread, void* ucontext) { +#ifdef LINUX + ucontext_t* uc = (ucontext_t*) ucontext; + + if (is_stwx(instruction) || is_stwux(instruction)) { + int ra = inv_ra_field(instruction); + int rb = inv_rb_field(instruction); + + // look up content of ra and rb in ucontext + address ra_val=(address)uc->uc_mcontext.regs->gpr[ra]; + long rb_val=(long)uc->uc_mcontext.regs->gpr[rb]; + return os::is_memory_serialize_page(thread, ra_val+rb_val); + } else if (is_stw(instruction) || is_stwu(instruction)) { + int ra = inv_ra_field(instruction); + int d1 = inv_d1_field(instruction); + + // look up content of ra in ucontext + address ra_val=(address)uc->uc_mcontext.regs->gpr[ra]; + return os::is_memory_serialize_page(thread, ra_val+d1); + } else { + return false; + } +#else + // workaround not needed on !LINUX :-) + ShouldNotCallThis(); + return false; +#endif +} + +void MacroAssembler::bang_stack_with_offset(int offset) { + // When increasing the stack, the old stack pointer will be written + // to the new top of stack according to the PPC64 abi. + // Therefore, stack banging is not necessary when increasing + // the stack by <= os::vm_page_size() bytes. + // When increasing the stack by a larger amount, this method is + // called repeatedly to bang the intermediate pages. + + // Stack grows down, caller passes positive offset. + assert(offset > 0, "must bang with positive offset"); + + long stdoffset = -offset; + + if (is_simm(stdoffset, 16)) { + // Signed 16 bit offset, a simple std is ok. + if (UseLoadInstructionsForStackBangingPPC64) { + ld(R0, (int)(signed short)stdoffset, R1_SP); + } else { + std(R0,(int)(signed short)stdoffset, R1_SP); + } + } else if (is_simm(stdoffset, 31)) { + const int hi = MacroAssembler::largeoffset_si16_si16_hi(stdoffset); + const int lo = MacroAssembler::largeoffset_si16_si16_lo(stdoffset); + + Register tmp = R11; + addis(tmp, R1_SP, hi); + if (UseLoadInstructionsForStackBangingPPC64) { + ld(R0, lo, tmp); + } else { + std(R0, lo, tmp); + } + } else { + ShouldNotReachHere(); + } +} + +// If instruction is a stack bang of the form +// std R0, x(Ry), (see bang_stack_with_offset()) +// stdu R1_SP, x(R1_SP), (see push_frame(), resize_frame()) +// or stdux R1_SP, Rx, R1_SP (see push_frame(), resize_frame()) +// return the banged address. Otherwise, return 0. +address MacroAssembler::get_stack_bang_address(int instruction, void *ucontext) { +#ifdef LINUX + ucontext_t* uc = (ucontext_t*) ucontext; + int rs = inv_rs_field(instruction); + int ra = inv_ra_field(instruction); + if ( (is_ld(instruction) && rs == 0 && UseLoadInstructionsForStackBangingPPC64) + || (is_std(instruction) && rs == 0 && !UseLoadInstructionsForStackBangingPPC64) + || (is_stdu(instruction) && rs == 1)) { + int ds = inv_ds_field(instruction); + // return banged address + return ds+(address)uc->uc_mcontext.regs->gpr[ra]; + } else if (is_stdux(instruction) && rs == 1) { + int rb = inv_rb_field(instruction); + address sp = (address)uc->uc_mcontext.regs->gpr[1]; + long rb_val = (long)uc->uc_mcontext.regs->gpr[rb]; + return ra != 1 || rb_val >= 0 ? NULL // not a stack bang + : sp + rb_val; // banged address + } + return NULL; // not a stack bang +#else + // workaround not needed on !LINUX :-) + ShouldNotCallThis(); + return NULL; +#endif +} + +// CmpxchgX sets condition register to cmpX(current, compare). +void MacroAssembler::cmpxchgw(ConditionRegister flag, Register dest_current_value, + Register compare_value, Register exchange_value, + Register addr_base, int semantics, bool cmpxchgx_hint, + Register int_flag_success, bool contention_hint) { + Label retry; + Label failed; + Label done; + + // Save one branch if result is returned via register and + // result register is different from the other ones. + bool use_result_reg = (int_flag_success != noreg); + bool preset_result_reg = (int_flag_success != dest_current_value && int_flag_success != compare_value && + int_flag_success != exchange_value && int_flag_success != addr_base); + + // release/fence semantics + if (semantics & MemBarRel) { + release(); + } + + if (use_result_reg && preset_result_reg) { + li(int_flag_success, 0); // preset (assume cas failed) + } + + // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM). + if (contention_hint) { // Don't try to reserve if cmp fails. + lwz(dest_current_value, 0, addr_base); + cmpw(flag, dest_current_value, compare_value); + bne(flag, failed); + } + + // atomic emulation loop + bind(retry); + + lwarx(dest_current_value, addr_base, cmpxchgx_hint); + cmpw(flag, dest_current_value, compare_value); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + bne_predict_not_taken(flag, failed); + } else { + bne( flag, failed); + } + // branch to done => (flag == ne), (dest_current_value != compare_value) + // fall through => (flag == eq), (dest_current_value == compare_value) + + stwcx_(exchange_value, addr_base); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + bne_predict_not_taken(CCR0, retry); // StXcx_ sets CCR0. + } else { + bne( CCR0, retry); // StXcx_ sets CCR0. + } + // fall through => (flag == eq), (dest_current_value == compare_value), (swapped) + + // Result in register (must do this at the end because int_flag_success can be the + // same register as one above). + if (use_result_reg) { + li(int_flag_success, 1); + } + + if (semantics & MemBarFenceAfter) { + fence(); + } else if (semantics & MemBarAcq) { + isync(); + } + + if (use_result_reg && !preset_result_reg) { + b(done); + } + + bind(failed); + if (use_result_reg && !preset_result_reg) { + li(int_flag_success, 0); + } + + bind(done); + // (flag == ne) => (dest_current_value != compare_value), (!swapped) + // (flag == eq) => (dest_current_value == compare_value), ( swapped) +} + +// Preforms atomic compare exchange: +// if (compare_value == *addr_base) +// *addr_base = exchange_value +// int_flag_success = 1; +// else +// int_flag_success = 0; +// +// ConditionRegister flag = cmp(compare_value, *addr_base) +// Register dest_current_value = *addr_base +// Register compare_value Used to compare with value in memory +// Register exchange_value Written to memory if compare_value == *addr_base +// Register addr_base The memory location to compareXChange +// Register int_flag_success Set to 1 if exchange_value was written to *addr_base +// +// To avoid the costly compare exchange the value is tested beforehand. +// Several special cases exist to avoid that unnecessary information is generated. +// +void MacroAssembler::cmpxchgd(ConditionRegister flag, + Register dest_current_value, Register compare_value, Register exchange_value, + Register addr_base, int semantics, bool cmpxchgx_hint, + Register int_flag_success, Label* failed_ext, bool contention_hint) { + Label retry; + Label failed_int; + Label& failed = (failed_ext != NULL) ? *failed_ext : failed_int; + Label done; + + // Save one branch if result is returned via register and result register is different from the other ones. + bool use_result_reg = (int_flag_success!=noreg); + bool preset_result_reg = (int_flag_success!=dest_current_value && int_flag_success!=compare_value && + int_flag_success!=exchange_value && int_flag_success!=addr_base); + assert(int_flag_success == noreg || failed_ext == NULL, "cannot have both"); + + // release/fence semantics + if (semantics & MemBarRel) { + release(); + } + + if (use_result_reg && preset_result_reg) { + li(int_flag_success, 0); // preset (assume cas failed) + } + + // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM). + if (contention_hint) { // Don't try to reserve if cmp fails. + ld(dest_current_value, 0, addr_base); + cmpd(flag, dest_current_value, compare_value); + bne(flag, failed); + } + + // atomic emulation loop + bind(retry); + + ldarx(dest_current_value, addr_base, cmpxchgx_hint); + cmpd(flag, dest_current_value, compare_value); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + bne_predict_not_taken(flag, failed); + } else { + bne( flag, failed); + } + + stdcx_(exchange_value, addr_base); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + bne_predict_not_taken(CCR0, retry); // stXcx_ sets CCR0 + } else { + bne( CCR0, retry); // stXcx_ sets CCR0 + } + + // result in register (must do this at the end because int_flag_success can be the same register as one above) + if (use_result_reg) { + li(int_flag_success, 1); + } + + // POWER6 doesn't need isync in CAS. + // Always emit isync to be on the safe side. + if (semantics & MemBarFenceAfter) { + fence(); + } else if (semantics & MemBarAcq) { + isync(); + } + + if (use_result_reg && !preset_result_reg) { + b(done); + } + + bind(failed_int); + if (use_result_reg && !preset_result_reg) { + li(int_flag_success, 0); + } + + bind(done); + // (flag == ne) => (dest_current_value != compare_value), (!swapped) + // (flag == eq) => (dest_current_value == compare_value), ( swapped) +} + +// Look up the method for a megamorphic invokeinterface call. +// The target method is determined by . +// The receiver klass is in recv_klass. +// On success, the result will be in method_result, and execution falls through. +// On failure, execution transfers to the given label. +void MacroAssembler::lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_temp, + Register sethi_temp, + Label& L_no_such_interface) { + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); + assert(itable_index.is_constant() || itable_index.as_register() == method_result, + "caller must use same register for non-constant itable index as for method"); + + // Compute start of first itableOffsetEntry (which is at the end of the vtable). + int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int itentry_off = itableMethodEntry::method_offset_in_bytes(); + int logMEsize = exact_log2(itableMethodEntry::size() * wordSize); + int scan_step = itableOffsetEntry::size() * wordSize; + int log_vte_size= exact_log2(vtableEntry::size() * wordSize); + + lwz(scan_temp, InstanceKlass::vtable_length_offset() * wordSize, recv_klass); + // %%% We should store the aligned, prescaled offset in the klassoop. + // Then the next several instructions would fold away. + + sldi(scan_temp, scan_temp, log_vte_size); + addi(scan_temp, scan_temp, vtable_base); + add(scan_temp, recv_klass, scan_temp); + + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + if (itable_index.is_register()) { + Register itable_offset = itable_index.as_register(); + sldi(itable_offset, itable_offset, logMEsize); + if (itentry_off) addi(itable_offset, itable_offset, itentry_off); + add(recv_klass, itable_offset, recv_klass); + } else { + long itable_offset = (long)itable_index.as_constant(); + load_const_optimized(sethi_temp, (itable_offset<itable(); scan->interface() != NULL; scan += scan_step) { + // if (scan->interface() == intf) { + // result = (klass + scan->offset() + itable_index); + // } + // } + Label search, found_method; + + for (int peel = 1; peel >= 0; peel--) { + // %%%% Could load both offset and interface in one ldx, if they were + // in the opposite order. This would save a load. + ld(method_result, itableOffsetEntry::interface_offset_in_bytes(), scan_temp); + + // Check that this entry is non-null. A null entry means that + // the receiver class doesn't implement the interface, and wasn't the + // same as when the caller was compiled. + cmpd(CCR0, method_result, intf_klass); + + if (peel) { + beq(CCR0, found_method); + } else { + bne(CCR0, search); + // (invert the test to fall through to found_method...) + } + + if (!peel) break; + + bind(search); + + cmpdi(CCR0, method_result, 0); + beq(CCR0, L_no_such_interface); + addi(scan_temp, scan_temp, scan_step); + } + + bind(found_method); + + // Got a hit. + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); + lwz(scan_temp, ito_offset, scan_temp); + ldx(method_result, scan_temp, recv_klass); +} + +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + + assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); + + const int base = InstanceKlass::vtable_start_offset() * wordSize; + assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + + if (vtable_index.is_register()) { + sldi(vtable_index.as_register(), vtable_index.as_register(), LogBytesPerWord); + add(recv_klass, vtable_index.as_register(), recv_klass); + } else { + addi(recv_klass, recv_klass, vtable_index.as_constant() << LogBytesPerWord); + } + ld(R19_method, base + vtableEntry::method_offset_in_bytes(), recv_klass); +} + +/////////////////////////////////////////// subtype checking //////////////////////////////////////////// + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label& L_success, + Label& L_failure) { + + const Register check_cache_offset = temp1_reg; + const Register cached_super = temp2_reg; + + assert_different_registers(sub_klass, super_klass, check_cache_offset, cached_super); + + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front of the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + cmpd(CCR0, sub_klass, super_klass); + beq(CCR0, L_success); + + // Check the supertype display: + lwz(check_cache_offset, sco_offset, super_klass); + // The loaded value is the offset from KlassOopDesc. + + ldx(cached_super, check_cache_offset, sub_klass); + cmpd(CCR0, cached_super, super_klass); + beq(CCR0, L_success); + + // This check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_cache and the primary super display elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + cmpwi(CCR0, check_cache_offset, sc_offset); + bne(CCR0, L_failure); + // bind(slow_path); // fallthru +} + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label* L_success, + Register result_reg) { + const Register array_ptr = temp1_reg; // current value from cache array + const Register temp = temp2_reg; + + assert_different_registers(sub_klass, super_klass, array_ptr, temp); + + int source_offset = in_bytes(Klass::secondary_supers_offset()); + int target_offset = in_bytes(Klass::secondary_super_cache_offset()); + + int length_offset = Array::length_offset_in_bytes(); + int base_offset = Array::base_offset_in_bytes(); + + Label hit, loop, failure, fallthru; + + ld(array_ptr, source_offset, sub_klass); + + //assert(4 == arrayOopDesc::length_length_in_bytes(), "precondition violated."); + lwz(temp, length_offset, array_ptr); + cmpwi(CCR0, temp, 0); + beq(CCR0, result_reg!=noreg ? failure : fallthru); // length 0 + + mtctr(temp); // load ctr + + bind(loop); + // Oops in table are NO MORE compressed. + ld(temp, base_offset, array_ptr); + cmpd(CCR0, temp, super_klass); + beq(CCR0, hit); + addi(array_ptr, array_ptr, BytesPerWord); + bdnz(loop); + + bind(failure); + if (result_reg!=noreg) li(result_reg, 1); // load non-zero result (indicates a miss) + b(fallthru); + + bind(hit); + std(super_klass, target_offset, sub_klass); // save result to cache + if (result_reg != noreg) li(result_reg, 0); // load zero result (indicates a hit) + if (L_success != NULL) b(*L_success); + + bind(fallthru); +} + +// Try fast path, then go to slow one if not successful +void MacroAssembler::check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label& L_success) { + Label L_failure; + check_klass_subtype_fast_path(sub_klass, super_klass, temp1_reg, temp2_reg, L_success, L_failure); + check_klass_subtype_slow_path(sub_klass, super_klass, temp1_reg, temp2_reg, &L_success); + bind(L_failure); // Fallthru if not successful. +} + +void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, + Register temp_reg, + Label& wrong_method_type) { + assert_different_registers(mtype_reg, mh_reg, temp_reg); + // Compare method type against that of the receiver. + load_heap_oop_not_null(temp_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg), mh_reg); + cmpd(CCR0, temp_reg, mtype_reg); + bne(CCR0, wrong_method_type); +} + +RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, + Register temp_reg, + int extra_slot_offset) { + // cf. TemplateTable::prepare_invoke(), if (load_receiver). + int stackElementSize = Interpreter::stackElementSize; + int offset = extra_slot_offset * stackElementSize; + if (arg_slot.is_constant()) { + offset += arg_slot.as_constant() * stackElementSize; + return offset; + } else { + assert(temp_reg != noreg, "must specify"); + sldi(temp_reg, arg_slot.as_register(), exact_log2(stackElementSize)); + if (offset != 0) + addi(temp_reg, temp_reg, offset); + return temp_reg; + } +} + +void MacroAssembler::biased_locking_enter(ConditionRegister cr_reg, Register obj_reg, + Register mark_reg, Register temp_reg, + Register temp2_reg, Label& done, Label* slow_case) { + assert(UseBiasedLocking, "why call this otherwise?"); + +#ifdef ASSERT + assert_different_registers(obj_reg, mark_reg, temp_reg, temp2_reg); +#endif + + Label cas_label; + + // Branch to done if fast path fails and no slow_case provided. + Label *slow_case_int = (slow_case != NULL) ? slow_case : &done; + + // Biased locking + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits + assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, + "biased locking makes assumptions about bit layout"); + + if (PrintBiasedLockingStatistics) { + load_const(temp_reg, (address) BiasedLocking::total_entry_count_addr(), temp2_reg); + lwz(temp2_reg, 0, temp_reg); + addi(temp2_reg, temp2_reg, 1); + stw(temp2_reg, 0, temp_reg); + } + + andi(temp_reg, mark_reg, markOopDesc::biased_lock_mask_in_place); + cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern); + bne(cr_reg, cas_label); + + load_klass_with_trap_null_check(temp_reg, obj_reg); + + load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place)); + ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); + orr(temp_reg, R16_thread, temp_reg); + xorr(temp_reg, mark_reg, temp_reg); + andr(temp_reg, temp_reg, temp2_reg); + cmpdi(cr_reg, temp_reg, 0); + if (PrintBiasedLockingStatistics) { + Label l; + bne(cr_reg, l); + load_const(mark_reg, (address) BiasedLocking::biased_lock_entry_count_addr()); + lwz(temp2_reg, 0, mark_reg); + addi(temp2_reg, temp2_reg, 1); + stw(temp2_reg, 0, mark_reg); + // restore mark_reg + ld(mark_reg, oopDesc::mark_offset_in_bytes(), obj_reg); + bind(l); + } + beq(cr_reg, done); + + Label try_revoke_bias; + Label try_rebias; + + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + andi(temp2_reg, temp_reg, markOopDesc::biased_lock_mask_in_place); + cmpwi(cr_reg, temp2_reg, 0); + bne(cr_reg, try_revoke_bias); + + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + + int shift_amount = 64 - markOopDesc::epoch_shift; + // rotate epoch bits to right (little) end and set other bits to 0 + // [ big part | epoch | little part ] -> [ 0..0 | epoch ] + rldicl_(temp2_reg, temp_reg, shift_amount, 64 - markOopDesc::epoch_bits); + // branch if epoch bits are != 0, i.e. they differ, because the epoch has been incremented + bne(CCR0, try_rebias); + + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + andi(mark_reg, mark_reg, (markOopDesc::biased_lock_mask_in_place | + markOopDesc::age_mask_in_place | + markOopDesc::epoch_mask_in_place)); + orr(temp_reg, R16_thread, mark_reg); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // CmpxchgX sets cr_reg to cmpX(temp2_reg, mark_reg). + fence(); // TODO: replace by MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq ? + cmpxchgd(/*flag=*/cr_reg, /*current_value=*/temp2_reg, + /*compare_value=*/mark_reg, /*exchange_value=*/temp_reg, + /*where=*/obj_reg, + MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, slow_case_int); // bail out if failed + + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + if (PrintBiasedLockingStatistics) { + load_const(temp_reg, (address) BiasedLocking::anonymously_biased_lock_entry_count_addr(), temp2_reg); + lwz(temp2_reg, 0, temp_reg); + addi(temp2_reg, temp2_reg, 1); + stw(temp2_reg, 0, temp_reg); + } + b(done); + + bind(try_rebias); + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place); + orr(temp_reg, R16_thread, temp_reg); + load_klass_with_trap_null_check(temp2_reg, obj_reg); + ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg); + orr(temp_reg, temp_reg, temp2_reg); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // CmpxchgX sets cr_reg to cmpX(temp2_reg, mark_reg). + fence(); // TODO: replace by MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq ? + cmpxchgd(/*flag=*/cr_reg, /*current_value=*/temp2_reg, + /*compare_value=*/mark_reg, /*exchange_value=*/temp_reg, + /*where=*/obj_reg, + MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, slow_case_int); // bail out if failed + + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + if (PrintBiasedLockingStatistics) { + load_const(temp_reg, (address) BiasedLocking::rebiased_lock_entry_count_addr(), temp2_reg); + lwz(temp2_reg, 0, temp_reg); + addi(temp2_reg, temp2_reg, 1); + stw(temp2_reg, 0, temp_reg); + } + b(done); + + bind(try_revoke_bias); + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + load_klass_with_trap_null_check(temp_reg, obj_reg); + ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); + andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place); + orr(temp_reg, temp_reg, temp2_reg); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // CmpxchgX sets cr_reg to cmpX(temp2_reg, mark_reg). + fence(); // TODO: replace by MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq ? + cmpxchgd(/*flag=*/cr_reg, /*current_value=*/temp2_reg, + /*compare_value=*/mark_reg, /*exchange_value=*/temp_reg, + /*where=*/obj_reg, + MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock()); + + // reload markOop in mark_reg before continuing with lightweight locking + ld(mark_reg, oopDesc::mark_offset_in_bytes(), obj_reg); + + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + if (PrintBiasedLockingStatistics) { + Label l; + bne(cr_reg, l); + load_const(temp_reg, (address) BiasedLocking::revoked_lock_entry_count_addr(), temp2_reg); + lwz(temp2_reg, 0, temp_reg); + addi(temp2_reg, temp2_reg, 1); + stw(temp2_reg, 0, temp_reg); + bind(l); + } + + bind(cas_label); +} + +void MacroAssembler::biased_locking_exit (ConditionRegister cr_reg, Register mark_addr, Register temp_reg, Label& done) { + // Check for biased locking unlock case, which is a no-op + // Note: we do not have to check the thread ID for two reasons. + // First, the interpreter checks for IllegalMonitorStateException at + // a higher level. Second, if the bias was revoked while we held the + // lock, the object could not be rebiased toward another thread, so + // the bias bit would be clear. + + ld(temp_reg, 0, mark_addr); + andi(temp_reg, temp_reg, markOopDesc::biased_lock_mask_in_place); + + cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern); + beq(cr_reg, done); +} + +// "The box" is the space on the stack where we copy the object mark. +void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register oop, Register box, + Register temp, Register displaced_header, Register current_header) { + assert_different_registers(oop, box, temp, displaced_header, current_header); + assert(flag != CCR0, "bad condition register"); + Label cont; + Label object_has_monitor; + Label cas_failed; + + // Load markOop from object into displaced_header. + ld(displaced_header, oopDesc::mark_offset_in_bytes(), oop); + + + // Always do locking in runtime. + if (EmitSync & 0x01) { + cmpdi(flag, oop, 0); // Oop can't be 0 here => always false. + return; + } + + if (UseBiasedLocking) { + biased_locking_enter(flag, oop, displaced_header, temp, current_header, cont); + } + + // Handle existing monitor. + if ((EmitSync & 0x02) == 0) { + // The object has an existing monitor iff (mark & monitor_value) != 0. + andi_(temp, displaced_header, markOopDesc::monitor_value); + bne(CCR0, object_has_monitor); + } + + // Set displaced_header to be (markOop of object | UNLOCK_VALUE). + ori(displaced_header, displaced_header, markOopDesc::unlocked_value); + + // Load Compare Value application register. + + // Initialize the box. (Must happen before we update the object mark!) + std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + + // Must fence, otherwise, preceding store(s) may float below cmpxchg. + // Compare object markOop with mark and if equal exchange scratch1 with object markOop. + // CmpxchgX sets cr_reg to cmpX(current, displaced). + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/displaced_header, + /*exchange_value=*/box, + /*where=*/oop, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, + &cas_failed); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // If the compare-and-exchange succeeded, then we found an unlocked + // object and we have now locked it. + b(cont); + + bind(cas_failed); + // We did not see an unlocked object so try the fast recursive case. + + // Check if the owner is self by comparing the value in the markOop of object + // (current_header) with the stack pointer. + sub(current_header, current_header, R1_SP); + load_const_optimized(temp, (address) (~(os::vm_page_size()-1) | + markOopDesc::lock_mask_in_place)); + + and_(R0/*==0?*/, current_header, temp); + // If condition is true we are cont and hence we can store 0 as the + // displaced header in the box, which indicates that it is a recursive lock. + mcrf(flag,CCR0); + std(R0/*==0, perhaps*/, BasicLock::displaced_header_offset_in_bytes(), box); + + // Handle existing monitor. + if ((EmitSync & 0x02) == 0) { + b(cont); + + bind(object_has_monitor); + // The object's monitor m is unlocked iff m->owner == NULL, + // otherwise m->owner may contain a thread or a stack address. + // + // Try to CAS m->owner from NULL to current thread. + addi(temp, displaced_header, ObjectMonitor::owner_offset_in_bytes()-markOopDesc::monitor_value); + li(displaced_header, 0); + // CmpxchgX sets flag to cmpX(current, displaced). + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/displaced_header, + /*exchange_value=*/R16_thread, + /*where=*/temp, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock()); + + // Store a non-null value into the box. + std(box, BasicLock::displaced_header_offset_in_bytes(), box); + +# ifdef ASSERT + bne(flag, cont); + // We have acquired the monitor, check some invariants. + addi(/*monitor=*/temp, temp, -ObjectMonitor::owner_offset_in_bytes()); + // Invariant 1: _recursions should be 0. + //assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size"); + asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp, + "monitor->_recursions should be 0", -1); + // Invariant 2: OwnerIsThread shouldn't be 0. + //assert(ObjectMonitor::OwnerIsThread_size_in_bytes() == 4, "unexpected size"); + //asm_assert_mem4_isnot_zero(ObjectMonitor::OwnerIsThread_offset_in_bytes(), temp, + // "monitor->OwnerIsThread shouldn't be 0", -1); +# endif + } + + bind(cont); + // flag == EQ indicates success + // flag == NE indicates failure +} + +void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box, + Register temp, Register displaced_header, Register current_header) { + assert_different_registers(oop, box, temp, displaced_header, current_header); + assert(flag != CCR0, "bad condition register"); + Label cont; + Label object_has_monitor; + + // Always do locking in runtime. + if (EmitSync & 0x01) { + cmpdi(flag, oop, 0); // Oop can't be 0 here => always false. + return; + } + + if (UseBiasedLocking) { + biased_locking_exit(flag, oop, current_header, cont); + } + + // Find the lock address and load the displaced header from the stack. + ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + + // If the displaced header is 0, we have a recursive unlock. + cmpdi(flag, displaced_header, 0); + beq(flag, cont); + + // Handle existing monitor. + if ((EmitSync & 0x02) == 0) { + // The object has an existing monitor iff (mark & monitor_value) != 0. + ld(current_header, oopDesc::mark_offset_in_bytes(), oop); + andi(temp, current_header, markOopDesc::monitor_value); + cmpdi(flag, temp, 0); + bne(flag, object_has_monitor); + } + + + // Check if it is still a light weight lock, this is is true if we see + // the stack address of the basicLock in the markOop of the object. + // Cmpxchg sets flag to cmpd(current_header, box). + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/box, + /*exchange_value=*/displaced_header, + /*where=*/oop, + MacroAssembler::MemBarRel, + MacroAssembler::cmpxchgx_hint_release_lock(), + noreg, + &cont); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // Handle existing monitor. + if ((EmitSync & 0x02) == 0) { + b(cont); + + bind(object_has_monitor); + addi(current_header, current_header, -markOopDesc::monitor_value); // monitor + ld(temp, ObjectMonitor::owner_offset_in_bytes(), current_header); + ld(displaced_header, ObjectMonitor::recursions_offset_in_bytes(), current_header); + xorr(temp, R16_thread, temp); // Will be 0 if we are the owner. + orr(temp, temp, displaced_header); // Will be 0 if there are 0 recursions. + cmpdi(flag, temp, 0); + bne(flag, cont); + + ld(temp, ObjectMonitor::EntryList_offset_in_bytes(), current_header); + ld(displaced_header, ObjectMonitor::cxq_offset_in_bytes(), current_header); + orr(temp, temp, displaced_header); // Will be 0 if both are 0. + cmpdi(flag, temp, 0); + bne(flag, cont); + release(); + std(temp, ObjectMonitor::owner_offset_in_bytes(), current_header); + } + + bind(cont); + // flag == EQ indicates success + // flag == NE indicates failure +} + +// Write serialization page so VM thread can do a pseudo remote membar. +// We use the current thread pointer to calculate a thread specific +// offset to write to within the page. This minimizes bus traffic +// due to cache line collision. +void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register tmp2) { + srdi(tmp2, thread, os::get_serialize_page_shift_count()); + + int mask = os::vm_page_size() - sizeof(int); + if (Assembler::is_simm(mask, 16)) { + andi(tmp2, tmp2, mask); + } else { + lis(tmp1, (int)((signed short) (mask >> 16))); + ori(tmp1, tmp1, mask & 0x0000ffff); + andr(tmp2, tmp2, tmp1); + } + + load_const(tmp1, (long) os::get_memory_serialize_page()); + release(); + stwx(R0, tmp1, tmp2); +} + + +// GC barrier helper macros + +// Write the card table byte if needed. +void MacroAssembler::card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp) { + CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::CardTableModRef || + bs->kind() == BarrierSet::CardTableExtension, "wrong barrier"); +#ifdef ASSERT + cmpdi(CCR0, Rnew_val, 0); + asm_assert_ne("null oop not allowed", 0x321); +#endif + card_table_write(bs->byte_map_base, Rtmp, Rstore_addr); +} + +// Write the card table byte. +void MacroAssembler::card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj) { + assert_different_registers(Robj, Rtmp, R0); + load_const_optimized(Rtmp, (address)byte_map_base, R0); + srdi(Robj, Robj, CardTableModRefBS::card_shift); + li(R0, 0); // dirty + if (UseConcMarkSweepGC) release(); + stbx(R0, Rtmp, Robj); +} + +#ifndef SERIALGC + +// General G1 pre-barrier generator. +// Goal: record the previous value if it is not null. +void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, + Register Rtmp1, Register Rtmp2, bool needs_frame) { + Label runtime, filtered; + + // Is marking active? + if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { + lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()), R16_thread); + } else { + guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); + lbz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()), R16_thread); + } + cmpdi(CCR0, Rtmp1, 0); + beq(CCR0, filtered); + + // Do we need to load the previous value? + if (Robj != noreg) { + // Load the previous value... + if (UseCompressedOops) { + lwz(Rpre_val, offset, Robj); + } else { + ld(Rpre_val, offset, Robj); + } + // Previous value has been loaded into Rpre_val. + } + assert(Rpre_val != noreg, "must have a real register"); + + // Is the previous value null? + cmpdi(CCR0, Rpre_val, 0); + beq(CCR0, filtered); + + if (Robj != noreg && UseCompressedOops) { + decode_heap_oop_not_null(Rpre_val); + } + + // OK, it's not filtered, so we'll need to call enqueue. In the normal + // case, pre_val will be a scratch G-reg, but there are some cases in + // which it's an O-reg. In the first case, do a normal call. In the + // latter, do a save here and call the frameless version. + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + const Register Rbuffer = Rtmp1, Rindex = Rtmp2; + + ld(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index()), R16_thread); + cmpdi(CCR0, Rindex, 0); + beq(CCR0, runtime); // If index == 0, goto runtime. + ld(Rbuffer, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()), R16_thread); + + addi(Rindex, Rindex, -wordSize); // Decrement index. + std(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index()), R16_thread); + + // Record the previous value. + stdx(Rpre_val, Rbuffer, Rindex); + b(filtered); + + bind(runtime); + + // VM call need frame to access(write) O register. + if (needs_frame) { + save_LR_CR(Rtmp1); + push_frame_abi112(0, Rtmp2); + } + + if (Rpre_val->is_volatile() && Robj == noreg) mr(R31, Rpre_val); // Save pre_val across C call if it was preloaded. + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_val, R16_thread); + if (Rpre_val->is_volatile() && Robj == noreg) mr(Rpre_val, R31); // restore + + if (needs_frame) { + pop_frame(); + restore_LR_CR(Rtmp1); + } + + bind(filtered); +} + +// General G1 post-barrier generator +// Store cross-region card. +void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1, Register Rtmp2, Register Rtmp3, Label *filtered_ext) { + Label runtime, filtered_int; + Label& filtered = (filtered_ext != NULL) ? *filtered_ext : filtered_int; + assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2); + + G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::G1SATBCT || + bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); + + // Does store cross heap regions? + if (G1RSBarrierRegionFilter) { + xorr(Rtmp1, Rstore_addr, Rnew_val); + srdi_(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes); + beq(CCR0, filtered); + } + + // Crosses regions, storing NULL? +#ifdef ASSERT + cmpdi(CCR0, Rnew_val, 0); + asm_assert_ne("null oop not allowed (G1)", 0x322); // Checked by caller on PPC64, so following branch is obsolete: + //beq(CCR0, filtered); +#endif + + // Storing region crossing non-NULL, is card already dirty? + assert(sizeof(*bs->byte_map_base) == sizeof(jbyte), "adjust this code"); + const Register Rcard_addr = Rtmp1; + Register Rbase = Rtmp2; + load_const_optimized(Rbase, (address)bs->byte_map_base, /*temp*/ Rtmp3); + + srdi(Rcard_addr, Rstore_addr, CardTableModRefBS::card_shift); + + // Get the address of the card. + lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); + + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); + cmpwi(CCR0, Rtmp3 /* card value */, 0); + beq(CCR0, filtered); + + // Storing a region crossing, non-NULL oop, card is clean. + // Dirty card and log. + li(Rtmp3, 0); // dirty + //release(); // G1: oops are allowed to get visible after dirty marking. + stbx(Rtmp3, Rbase, Rcard_addr); + + add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued. + Rbase = noreg; // end of lifetime + + const Register Rqueue_index = Rtmp2, + Rqueue_buf = Rtmp3; + ld(Rqueue_index, in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()), R16_thread); + cmpdi(CCR0, Rqueue_index, 0); + beq(CCR0, runtime); // index == 0 then jump to runtime + ld(Rqueue_buf, in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()), R16_thread); + + addi(Rqueue_index, Rqueue_index, -wordSize); // decrement index + std(Rqueue_index, in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()), R16_thread); + + stdx(Rcard_addr, Rqueue_buf, Rqueue_index); // store card + b(filtered); + + bind(runtime); + + // Save the live input values. + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread); + + bind(filtered_int); +} +#endif // SERIALGC + +// Values for last_Java_pc, and last_Java_sp must comply to the rules +// in frame_ppc64.hpp. +void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { + // Always set last_Java_pc and flags first because once last_Java_sp + // is visible has_last_Java_frame is true and users will look at the + // rest of the fields. (Note: flags should always be zero before we + // get here so doesn't need to be set.) + + // Verify that last_Java_pc was zeroed on return to Java + asm_assert_mem8_is_zero(in_bytes(JavaThread::last_Java_pc_offset()), R16_thread, + "last_Java_pc not zeroed before leaving Java", 0x200); + + // When returning from calling out from Java mode the frame anchor's + // last_Java_pc will always be set to NULL. It is set here so that + // if we are doing a call to native (not VM) that we capture the + // known pc and don't have to rely on the native call having a + // standard frame linkage where we can find the pc. + if (last_Java_pc != noreg) + std(last_Java_pc, in_bytes(JavaThread::last_Java_pc_offset()), R16_thread); + + // set last_Java_sp last + std(last_Java_sp, in_bytes(JavaThread::last_Java_sp_offset()), R16_thread); +} + +void MacroAssembler::reset_last_Java_frame(void) { + asm_assert_mem8_isnot_zero(in_bytes(JavaThread::last_Java_sp_offset()), + R16_thread, "SP was not set, still zero", 0x202); + + BLOCK_COMMENT("reset_last_Java_frame {"); + li(R0, 0); + + // _last_Java_sp = 0 + std(R0, in_bytes(JavaThread::last_Java_sp_offset()), R16_thread); + + // _last_Java_pc = 0 + std(R0, in_bytes(JavaThread::last_Java_pc_offset()), R16_thread); + BLOCK_COMMENT("} reset_last_Java_frame"); +} + +void MacroAssembler::set_top_ijava_frame_at_SP_as_last_Java_frame(Register sp, Register tmp1) { + assert_different_registers(sp, tmp1); + + // sp points to a TOP_IJAVA_FRAME, retrieve frame's PC via + // TOP_IJAVA_FRAME_ABI. + // FIXME: assert that we really have a TOP_IJAVA_FRAME here! +#ifdef CC_INTERP + ld(tmp1/*pc*/, _top_ijava_frame_abi(frame_manager_lr), sp); +#else + Unimplemented(); +#endif + + set_last_Java_frame(/*sp=*/sp, /*pc=*/tmp1); +} + +void MacroAssembler::get_vm_result(Register oop_result) { + // Read: + // R16_thread + // R16_thread->in_bytes(JavaThread::vm_result_offset()) + // + // Updated: + // oop_result + // R16_thread->in_bytes(JavaThread::vm_result_offset()) + + ld(oop_result, in_bytes(JavaThread::vm_result_offset()), R16_thread); + li(R0, 0); + std(R0, in_bytes(JavaThread::vm_result_offset()), R16_thread); + + verify_oop(oop_result); +} + +void MacroAssembler::get_vm_result_2(Register metadata_result) { + // Read: + // R16_thread + // R16_thread->in_bytes(JavaThread::vm_result_2_offset()) + // + // Updated: + // metadata_result + // R16_thread->in_bytes(JavaThread::vm_result_2_offset()) + + ld(metadata_result, in_bytes(JavaThread::vm_result_2_offset()), R16_thread); + li(R0, 0); + std(R0, in_bytes(JavaThread::vm_result_2_offset()), R16_thread); +} + + +void MacroAssembler::encode_klass_not_null(Register dst, Register src) { + if (src == noreg) src = dst; + if (Universe::narrow_klass_base() != NULL) { + // heapbased + assert(Universe::narrow_klass_shift() != 0, "sanity"); + sub(dst, src, R30); + srdi(dst, dst, Universe::narrow_klass_shift()); + } else if (Universe::narrow_klass_shift() != 0) { + // zerobased + srdi(dst, src, Universe::narrow_klass_shift()); + } else if (src != dst) { + // unscaled + mr(dst, src); + } +} + +void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) { + if (UseCompressedKlassPointers) { + encode_klass_not_null(ck, klass); + stw(ck, oopDesc::klass_offset_in_bytes(), dst_oop); + } else { + std(klass, oopDesc::klass_offset_in_bytes(), dst_oop); + } +} + +void MacroAssembler::decode_klass_not_null(Register dst, Register src) { + if (src == noreg) src = dst; + if (Universe::narrow_klass_base() != NULL) { + // heapbased + assert(Universe::narrow_klass_shift() != 0, "sanity"); + sldi(dst, src, Universe::narrow_klass_shift()); + add(dst, dst, R30); + } else if (Universe::narrow_klass_shift() != 0) { + // zerobased + sldi(dst, src, Universe::narrow_klass_shift()); + } else if (src != dst) { + // unscaled + mr(dst, src); + } +} + +void MacroAssembler::load_klass(Register dst, Register src) { + if (UseCompressedKlassPointers) { + lwz(dst, oopDesc::klass_offset_in_bytes(), src); + // Attention: no null check here! + decode_klass_not_null(dst, dst); + } else { + ld(dst, oopDesc::klass_offset_in_bytes(), src); + } +} + +void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) { + if (false NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + trap_null_check(src); + } + } + load_klass(dst, src); +} + +void MacroAssembler::reinit_heapbase(Register d, Register tmp) { + if (UseCompressedOops || UseCompressedKlassPointers) { + load_const(R30, Universe::narrow_ptrs_base_addr(), tmp); + ld(R30, 0, R30); + } +} + +/////////////////////////////////////////// String intrinsics //////////////////////////////////////////// + +// Search for a single jchar in an jchar[]. +// +// Assumes that result differs from all other registers. +// +// Haystack, needle are the addresses of jchar-arrays. +// NeedleChar is needle[0] if it is known at compile time. +// Haycnt is the length of the haystack. We assume haycnt >=1. +// +// Preserves haystack, haycnt, kills all other registers. +// +// If needle == R0, we search for the constant needleChar. +void MacroAssembler::string_indexof_1(Register result, Register haystack, Register haycnt, + Register needle, jchar needleChar, + Register tmp1, Register tmp2) { + + assert_different_registers(result, haystack, haycnt, needle, tmp1, tmp2); + + Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_Found3, L_NotFound, L_End; + Register needle0 = needle, // Contains needle[0]. + addr = tmp1, + ch1 = tmp2, + ch2 = R0; + +//2 (variable) or 3 (const): + if (needle != R0) lhz(needle0, 0, needle); // Preload needle character, needle has len==1. + dcbtct(haystack, 0x00); // Indicate R/O access to haystack. + + srwi_(tmp2, haycnt, 1); // Shift right by exact_log2(UNROLL_FACTOR). + mr(addr, haystack); + beq(CCR0, L_FinalCheck); + mtctr(tmp2); // Move to count register. +//8: + bind(L_InnerLoop); // Main work horse (2x unrolled search loop). + lhz(ch1, 0, addr); // Load characters from haystack. + lhz(ch2, 2, addr); + (needle != R0) ? cmpw(CCR0, ch1, needle0) : cmplwi(CCR0, ch1, needleChar); + (needle != R0) ? cmpw(CCR1, ch2, needle0) : cmplwi(CCR1, ch2, needleChar); + beq(CCR0, L_Found1); // Did we find the needle? + beq(CCR1, L_Found2); + addi(addr, addr, 4); + bdnz(L_InnerLoop); +//16: + bind(L_FinalCheck); + andi_(R0, haycnt, 1); + beq(CCR0, L_NotFound); + lhz(ch1, 0, addr); // One position left at which we have to compare. + (needle != R0) ? cmpw(CCR1, ch1, needle0) : cmplwi(CCR1, ch1, needleChar); + beq(CCR1, L_Found3); +//21: + bind(L_NotFound); + li(result, -1); // Not found. + b(L_End); + + bind(L_Found2); + addi(addr, addr, 2); +//24: + bind(L_Found1); + bind(L_Found3); // Return index ... + subf(addr, haystack, addr); // relative to haystack, + srdi(result, addr, 1); // in characters. + bind(L_End); +} + + +// Implementation of IndexOf for jchar arrays. +// +// The length of haystack and needle are not constant, i.e. passed in a register. +// +// Preserves registers haystack, needle. +// Kills registers haycnt, needlecnt. +// Assumes that result differs from all other registers. +// Haystack, needle are the addresses of jchar-arrays. +// Haycnt, needlecnt are the lengths of them, respectively. +// +// Needlecntval must be zero or 15-bit unsigned immediate and > 1. +void MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt, + Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval, + Register tmp1, Register tmp2, Register tmp3, Register tmp4) { + + // Ensure 0=2, bail out otherwise. + // ************************************************************************************************** + +//1 (variable) or 3 (const): + dcbtct(needle, 0x00); // Indicate R/O access to str1. + dcbtct(haystack, 0x00); // Indicate R/O access to str2. + + // Compute last haystack addr to use if no match gets found. + if (needlecntval == 0) { // variable needlecnt +//3: + subf(ch1, needlecnt, haycnt); // Last character index to compare is haycnt-needlecnt. + addi(addr, haystack, -2); // Accesses use pre-increment. + cmpwi(CCR6, needlecnt, 2); + blt(CCR6, L_TooShort); // Variable needlecnt: handle short needle separately. + slwi(ch1, ch1, 1); // Scale to number of bytes. + lwz(n_start, 0, needle); // Load first 2 characters of needle. + add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)). + addi(needlecnt, needlecnt, -2); // Rest of needle. + } else { // constant needlecnt + guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately"); + assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate"); +//5: + addi(ch1, haycnt, -needlecntval); // Last character index to compare is haycnt-needlecnt. + lwz(n_start, 0, needle); // Load first 2 characters of needle. + addi(addr, haystack, -2); // Accesses use pre-increment. + slwi(ch1, ch1, 1); // Scale to number of bytes. + add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)). + li(needlecnt, needlecntval-2); // Rest of needle. + } + + // Main Loop (now we have at least 3 characters). +//11: + Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2, L_Comp3; + bind(L_OuterLoop); // Search for 1st 2 characters. + Register addr_diff = tmp4; + subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check. + addi(addr, addr, 2); // This is the new address we want to use for comparing. + srdi_(ch2, addr_diff, 2); + beq(CCR0, L_FinalCheck); // 2 characters left? + mtctr(ch2); // addr_diff/4 +//16: + bind(L_InnerLoop); // Main work horse (2x unrolled search loop) + lwz(ch1, 0, addr); // Load 2 characters of haystack (ignore alignment). + lwz(ch2, 2, addr); + cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop). + cmpw(CCR1, ch2, n_start); + beq(CCR0, L_Comp1); // Did we find the needle start? + beq(CCR1, L_Comp2); + addi(addr, addr, 4); + bdnz(L_InnerLoop); +//24: + bind(L_FinalCheck); + rldicl_(addr_diff, addr_diff, 64-1, 63); // Remaining characters not covered by InnerLoop: (addr_diff>>1)&1. + beq(CCR0, L_NotFound); + lwz(ch1, 0, addr); // One position left at which we have to compare. + cmpw(CCR1, ch1, n_start); + beq(CCR1, L_Comp3); +//29: + bind(L_NotFound); + li(result, -1); // not found + b(L_End); + + + // ************************************************************************************************** + // Special Case: unfortunately, the variable needle case can be called with needlecnt<2 + // ************************************************************************************************** +//31: + if ((needlecntval>>1) !=1 ) { // Const needlecnt is 2 or 3? Reduce code size. + int nopcnt = 5; + if (needlecntval !=0 ) ++nopcnt; // Balance alignment (other case: see below). + if (needlecntval == 0) { // We have to handle these cases separately. + Label L_OneCharLoop; + bind(L_TooShort); + mtctr(haycnt); + lhz(n_start, 0, needle); // First character of needle + bind(L_OneCharLoop); + lhzu(ch1, 2, addr); + cmpw(CCR1, ch1, n_start); + beq(CCR1, L_Found); // Did we find the one character needle? + bdnz(L_OneCharLoop); + li(result, -1); // Not found. + b(L_End); + } // 8 instructions, so no impact on alignment. + for (int x = 0; x < nopcnt; ++x) nop(); + } + + // ************************************************************************************************** + // Regular Case Part II: compare rest of needle (first 2 characters have been compared already) + // ************************************************************************************************** + + // Compare the rest +//36 if needlecntval==0, else 37: + bind(L_Comp2); + addi(addr, addr, 2); // First comparison has failed, 2nd one hit. + bind(L_Comp1); // Addr points to possible needle start. + bind(L_Comp3); // Could have created a copy and use a different return address but saving code size here. + if (needlecntval != 2) { // Const needlecnt==2? + if (needlecntval != 3) { + if (needlecntval == 0) beq(CCR6, L_Found); // Variable needlecnt==2? + Register ind_reg = tmp4; + li(ind_reg, 2*2); // First 2 characters are already compared, use index 2. + mtctr(needlecnt); // Decremented by 2, still > 0. +//40: + Label L_CompLoop; + bind(L_CompLoop); + lhzx(ch2, needle, ind_reg); + lhzx(ch1, addr, ind_reg); + cmpw(CCR1, ch1, ch2); + bne(CCR1, L_OuterLoop); + addi(ind_reg, ind_reg, 2); + bdnz(L_CompLoop); + } else { // No loop required if there's only one needle character left. + lhz(ch2, 2*2, needle); + lhz(ch1, 2*2, addr); + cmpw(CCR1, ch1, ch2); + bne(CCR1, L_OuterLoop); + } + } + // Return index ... +//46: + bind(L_Found); + subf(addr, haystack, addr); // relative to haystack, ... + srdi(result, addr, 1); // in characters. +//48: + bind(L_End); +} + +// Implementation of Compare for jchar arrays. +// +// Kills the registers str1, str2, cnt1, cnt2. +// Kills cr0, ctr. +// Assumes that result differes from the input registers. +void MacroAssembler::string_compare(Register str1_reg, Register str2_reg, Register cnt1_reg, Register cnt2_reg, + Register result_reg, Register tmp_reg) { + assert_different_registers(result_reg, str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp_reg); + + Label Ldone, Lslow_case, Lslow_loop, Lfast_loop; + Register cnt_diff = R0, + limit_reg = cnt1_reg, + chr1_reg = result_reg, + chr2_reg = cnt2_reg, + addr_diff = str2_reg; + + // Offset 0 should be 32 byte aligned. +//-4: + dcbtct(str1_reg, 0x00); // Indicate R/O access to str1. + dcbtct(str2_reg, 0x00); // Indicate R/O access to str2. +//-2: + // Compute min(cnt1, cnt2) and check if 0 (bail out if we don't need to compare characters). + subf(result_reg, cnt2_reg, cnt1_reg); // difference between cnt1/2 + subf_(addr_diff, str1_reg, str2_reg); // alias? + beq(CCR0, Ldone); // return cnt difference if both ones are identical + srawi(limit_reg, result_reg, 31); // generate signmask (cnt1/2 must be non-negative so cnt_diff can't overflow) + mr(cnt_diff, result_reg); + andr(limit_reg, result_reg, limit_reg); // difference or zero (negative): cnt14 characters for fast loop + andi(limit_reg, tmp_reg, 4-1); // remaining characters + + // Adapt str1_reg str2_reg for the first loop iteration + mtctr(chr2_reg); // (min(cnt1, cnt2)-1)/4 + addi(limit_reg, limit_reg, 4+1); // compare last 5-8 characters in slow_case if mismatch found in fast_loop +//16: + // Compare the rest of the characters + bind(Lfast_loop); + ld(chr1_reg, 0, str1_reg); + ldx(chr2_reg, str1_reg, addr_diff); + cmpd(CCR0, chr2_reg, chr1_reg); + bne(CCR0, Lslow_case); // return chr1_reg + addi(str1_reg, str1_reg, 4*2); + bdnz(Lfast_loop); + addi(limit_reg, limit_reg, -4); // no mismatch found in fast_loop, only 1-4 characters missing +//23: + bind(Lslow_case); + mtctr(limit_reg); +//24: + bind(Lslow_loop); + lhz(chr1_reg, 0, str1_reg); + lhzx(chr2_reg, str1_reg, addr_diff); + subf_(result_reg, chr2_reg, chr1_reg); + bne(CCR0, Ldone); // return chr1_reg + addi(str1_reg, str1_reg, 1*2); + bdnz(Lslow_loop); +//30: + // If strings are equal up to min length, return the length difference. + mr(result_reg, cnt_diff); + nop(); // alignment +//32: + // Otherwise, return the difference between the first mismatched chars. + bind(Ldone); +} + + +// Compare char[] arrays. +// +// str1_reg USE only +// str2_reg USE only +// cnt_reg USE_DEF, due to tmp reg shortage +// result_reg DEF only, might compromise USE only registers +void MacroAssembler::char_arrays_equals(Register str1_reg, Register str2_reg, Register cnt_reg, Register result_reg, + Register tmp1_reg, Register tmp2_reg, Register tmp3_reg, Register tmp4_reg, + Register tmp5_reg) { + + // Str1 may be the same register as str2 which can occur e.g. after scalar replacement. + assert_different_registers(result_reg, str1_reg, cnt_reg, tmp1_reg, tmp2_reg, tmp3_reg, tmp4_reg, tmp5_reg); + assert_different_registers(result_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, tmp3_reg, tmp4_reg, tmp5_reg); + + // Offset 0 should be 32 byte aligned. + Label Linit_cbc, Lcbc, Lloop, Ldone_true, Ldone_false; + Register index_reg = tmp5_reg; + Register cbc_iter = tmp4_reg; + +//-1: + dcbtct(str1_reg, 0x00); // Indicate R/O access to str1. + dcbtct(str2_reg, 0x00); // Indicate R/O access to str2. +//1: + andi(cbc_iter, cnt_reg, 4-1); // Remaining iterations after 4 java characters per iteration loop. + li(index_reg, 0); // init + li(result_reg, 0); // assume false + srwi_(tmp2_reg, cnt_reg, exact_log2(4)); // Div: 4 java characters per iteration (main loop). + + cmpwi(CCR1, cbc_iter, 0); // CCR1 = (cbc_iter==0) + beq(CCR0, Linit_cbc); // too short + mtctr(tmp2_reg); +//8: + bind(Lloop); + ldx(tmp1_reg, str1_reg, index_reg); + ldx(tmp2_reg, str2_reg, index_reg); + cmpd(CCR0, tmp1_reg, tmp2_reg); + bne(CCR0, Ldone_false); // Unequal char pair found -> done. + addi(index_reg, index_reg, 4*sizeof(jchar)); + bdnz(Lloop); +//14: + bind(Linit_cbc); + beq(CCR1, Ldone_true); + mtctr(cbc_iter); +//16: + bind(Lcbc); + lhzx(tmp1_reg, str1_reg, index_reg); + lhzx(tmp2_reg, str2_reg, index_reg); + cmpw(CCR0, tmp1_reg, tmp2_reg); + bne(CCR0, Ldone_false); // Unequal char pair found -> done. + addi(index_reg, index_reg, 1*sizeof(jchar)); + bdnz(Lcbc); + nop(); + bind(Ldone_true); + li(result_reg, 1); +//24: + bind(Ldone_false); +} + + +void MacroAssembler::char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg, + Register tmp1_reg, Register tmp2_reg) { + // Str1 may be the same register as str2 which can occur e.g. after scalar replacement. + assert_different_registers(result_reg, str1_reg, tmp1_reg, tmp2_reg); + assert_different_registers(result_reg, str2_reg, tmp1_reg, tmp2_reg); + assert(sizeof(jchar) == 2, "must be"); + assert(cntval >= 0 && ((cntval & 0x7fff) == cntval), "wrong immediate"); + + Label Ldone_false; + + if (cntval < 16) { // short case + if (cntval != 0) li(result_reg, 0); // assume false + + const int num_bytes = cntval*sizeof(jchar); + int index = 0; + for (int next_index; (next_index = index + 8) <= num_bytes; index = next_index) { + ld(tmp1_reg, index, str1_reg); + ld(tmp2_reg, index, str2_reg); + cmpd(CCR0, tmp1_reg, tmp2_reg); + bne(CCR0, Ldone_false); + } + if (cntval & 2) { + lwz(tmp1_reg, index, str1_reg); + lwz(tmp2_reg, index, str2_reg); + cmpw(CCR0, tmp1_reg, tmp2_reg); + bne(CCR0, Ldone_false); + index += 4; + } + if (cntval & 1) { + lhz(tmp1_reg, index, str1_reg); + lhz(tmp2_reg, index, str2_reg); + cmpw(CCR0, tmp1_reg, tmp2_reg); + bne(CCR0, Ldone_false); + } + // fallthrough: true + } else { + Label Lloop; + Register index_reg = tmp1_reg; + const int loopcnt = cntval/4; + assert(loopcnt > 0, "must be"); + // Offset 0 should be 32 byte aligned. + //2: + dcbtct(str1_reg, 0x00); // Indicate R/O access to str1. + dcbtct(str2_reg, 0x00); // Indicate R/O access to str2. + li(tmp2_reg, loopcnt); + li(index_reg, 0); // init + li(result_reg, 0); // assume false + mtctr(tmp2_reg); + //8: + bind(Lloop); + ldx(R0, str1_reg, index_reg); + ldx(tmp2_reg, str2_reg, index_reg); + cmpd(CCR0, R0, tmp2_reg); + bne(CCR0, Ldone_false); // Unequal char pair found -> done. + addi(index_reg, index_reg, 4*sizeof(jchar)); + bdnz(Lloop); + //14: + if (cntval & 2) { + lwzx(R0, str1_reg, index_reg); + lwzx(tmp2_reg, str2_reg, index_reg); + cmpw(CCR0, R0, tmp2_reg); + bne(CCR0, Ldone_false); + if (cntval & 1) addi(index_reg, index_reg, 2*sizeof(jchar)); + } + if (cntval & 1) { + lhzx(R0, str1_reg, index_reg); + lhzx(tmp2_reg, str2_reg, index_reg); + cmpw(CCR0, R0, tmp2_reg); + bne(CCR0, Ldone_false); + } + // fallthru: true + } + li(result_reg, 1); + bind(Ldone_false); +} + + +void MacroAssembler::asm_assert(bool check_equal, const char *msg, int id) { +#ifdef ASSERT + Label ok; + if (check_equal) { + beq(CCR0, ok); + } else { + bne(CCR0, ok); + } + stop(msg, id); + bind(ok); +#endif +} + +void MacroAssembler::asm_assert_mems_zero(bool check_equal, int size, int mem_offset, + Register mem_base, const char* msg, int id) { +#ifdef ASSERT + switch (size) { + case 4: + lwz(R0, mem_offset, mem_base); + cmpwi(CCR0, R0, 0); + break; + case 8: + ld(R0, mem_offset, mem_base); + cmpdi(CCR0, R0, 0); + break; + default: + ShouldNotReachHere(); + } + asm_assert(check_equal, msg, id); +#endif // ASSERT +} + +void MacroAssembler::verify_thread() { + if (VerifyThread) { + unimplemented("'VerifyThread' currently not implemented on PPC"); + } +} + +// READ: oop. KILL: R0. Volatile floats perhaps. +void MacroAssembler::verify_oop(Register oop, const char* msg) { + if (!VerifyOops) { + return; + } + // will be preserved. + Register tmp = R11; + assert(oop != tmp, "precondition"); + unsigned int nbytes_save = 10*8; // 10 volatile gprs + address/* FunctionDescriptor** */fd = + StubRoutines::verify_oop_subroutine_entry_address(); + // save tmp + mr(R0, tmp); + // kill tmp + save_LR_CR(tmp); + push_frame_abi112(nbytes_save, tmp); + // restore tmp + mr(tmp, R0); + save_volatile_gprs(R1_SP, 112); // except R0 + // load FunctionDescriptor** + load_const(tmp, fd); + // load FunctionDescriptor* + ld(tmp, 0, tmp); + mr(R4_ARG2, oop); + load_const(R3_ARG1, (address)msg); + // call destination for its side effect + call_c(tmp); + restore_volatile_gprs(R1_SP, 112); // except R0 + pop_frame(); + // save tmp + mr(R0, tmp); + // kill tmp + restore_LR_CR(tmp); + // restore tmp + mr(tmp, R0); +} + +const char* stop_types[] = { + "stop", + "untested", + "unimplemented", + "shouldnotreachhere" +}; + +static void stop_on_request(int tp, const char* msg) { + tty->print("PPC assembly code requires stop: (%s) %s\n", (void *)stop_types[tp%/*stop_end*/4], msg); + guarantee(false, err_msg("PPC assembly code requires stop: %s", msg)); +} + +// Call a C-function that prints output. +void MacroAssembler::stop(int type, const char* msg, int id) { +#ifndef PRODUCT + block_comment(err_msg("stop: %s %s {", stop_types[type%stop_end], msg)); +#else + block_comment("stop {"); +#endif + + // setup arguments + load_const_optimized(R3_ARG1, type); + load_const_optimized(R4_ARG2, (void *)msg, /*tmp=*/R0); + call_VM_leaf(CAST_FROM_FN_PTR(address, stop_on_request), R3_ARG1, R4_ARG2); + illtrap(); + emit_int32(id); + block_comment("} stop;"); +} + +#ifndef PRODUCT +// Write pattern 0x0101010101010101 in memory region [low-before, high+after]. +// Val, addr are temp registers. +// If low == addr, addr is killed. +// High is preserved. +void MacroAssembler::zap_from_to(Register low, int before, Register high, int after, Register val, Register addr) { + if (!ZapMemory) return; + + assert_different_registers(low, val); + + BLOCK_COMMENT("zap memory region {"); + load_const_optimized(val, 0x0101010101010101); + int size = before + after; + if (low == high && size < 5 && size > 0) { + int offset = -before*BytesPerWord; + for (int i = 0; i < size; ++i) { + std(val, offset, low); + offset += (1*BytesPerWord); + } + } else { + addi(addr, low, -before*BytesPerWord); + assert_different_registers(high, val); + if (after) addi(high, high, after * BytesPerWord); + Label loop; + bind(loop); + std(val, 0, addr); + addi(addr, addr, 8); + cmpd(CCR6, addr, high); + ble(CCR6, loop); + if (after) addi(high, high, -after * BytesPerWord); // Correct back to old value. + } + BLOCK_COMMENT("} zap memory region"); +} + +#endif // !PRODUCT diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp new file mode 100644 index 00000000000..35d51499133 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_MACROASSEMBLER_PPC_HPP +#define CPU_PPC_VM_MACROASSEMBLER_PPC_HPP + +#include "asm/assembler.hpp" + +// MacroAssembler extends Assembler by a few frequently used macros. + +class ciTypeArray; + +class MacroAssembler: public Assembler { + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + + // + // Optimized instruction emitters + // + + inline static int largeoffset_si16_si16_hi(int si31) { return (si31 + (1<<15)) >> 16; } + inline static int largeoffset_si16_si16_lo(int si31) { return si31 - (((si31 + (1<<15)) >> 16) << 16); } + + // load d = *[a+si31] + // Emits several instructions if the offset is not encodable in one instruction. + void ld_largeoffset_unchecked(Register d, int si31, Register a, int emit_filler_nop); + void ld_largeoffset (Register d, int si31, Register a, int emit_filler_nop); + inline static bool is_ld_largeoffset(address a); + inline static int get_ld_largeoffset_offset(address a); + + inline void round_to(Register r, int modulus); + + // Load/store with type given by parameter. + void load_sized_value( Register dst, RegisterOrConstant offs, Register base, size_t size_in_bytes, bool is_signed); + void store_sized_value(Register dst, RegisterOrConstant offs, Register base, size_t size_in_bytes); + + // Move register if destination register and target register are different + inline void mr_if_needed(Register rd, Register rs); + + // nop padding + void align(int modulus); + + // + // Constants, loading constants, TOC support + // + + // Address of the global TOC. + inline static address global_toc(); + // Offset of given address to the global TOC. + inline static int offset_to_global_toc(const address addr); + + // Address of TOC of the current method. + inline address method_toc(); + // Offset of given address to TOC of the current method. + inline int offset_to_method_toc(const address addr); + + // Global TOC. + void calculate_address_from_global_toc(Register dst, address addr, + bool hi16 = true, bool lo16 = true, + bool add_relocation = true, bool emit_dummy_addr = false); + inline void calculate_address_from_global_toc_hi16only(Register dst, address addr) { + calculate_address_from_global_toc(dst, addr, true, false); + }; + inline void calculate_address_from_global_toc_lo16only(Register dst, address addr) { + calculate_address_from_global_toc(dst, addr, false, true); + }; + + inline static bool is_calculate_address_from_global_toc_at(address a, address bound); + static int patch_calculate_address_from_global_toc_at(address a, address addr, address bound); + static address get_address_of_calculate_address_from_global_toc_at(address a, address addr); + +#ifdef _LP64 + // Patch narrow oop constant. + inline static bool is_set_narrow_oop(address a, address bound); + static int patch_set_narrow_oop(address a, address bound, narrowOop data); + static narrowOop get_narrow_oop(address a, address bound); +#endif + + inline static bool is_load_const_at(address a); + + // Emits an oop const to the constant pool, loads the constant, and + // sets a relocation info with address current_pc. + void load_const_from_method_toc(Register dst, AddressLiteral& a, Register toc); + void load_toc_from_toc(Register dst, AddressLiteral& a, Register toc) { + assert(dst == R2_TOC, "base register must be TOC"); + load_const_from_method_toc(dst, a, toc); + } + + static bool is_load_const_from_method_toc_at(address a); + static int get_offset_of_load_const_from_method_toc_at(address a); + + // Get the 64 bit constant from a `load_const' sequence. + static long get_const(address load_const); + + // Patch the 64 bit constant of a `load_const' sequence. This is a + // low level procedure. It neither flushes the instruction cache nor + // is it atomic. + static void patch_const(address load_const, long x); + + // Metadata in code that we have to keep track of. + AddressLiteral allocate_metadata_address(Metadata* obj); // allocate_index + AddressLiteral constant_metadata_address(Metadata* obj); // find_index + // Oops used directly in compiled code are stored in the constant pool, + // and loaded from there. + // Allocate new entry for oop in constant pool. Generate relocation. + AddressLiteral allocate_oop_address(jobject obj); + // Find oop obj in constant pool. Return relocation with it's index. + AddressLiteral constant_oop_address(jobject obj); + + // Find oop in constant pool and emit instructions to load it. + // Uses constant_oop_address. + inline void set_oop_constant(jobject obj, Register d); + // Same as load_address. + inline void set_oop (AddressLiteral obj_addr, Register d); + + // Read runtime constant: Issue load if constant not yet established, + // else use real constant. + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset); + + // + // branch, jump + // + + inline void pd_patch_instruction(address branch, address target); + NOT_PRODUCT(static void pd_print_patched_instruction(address branch);) + + // Conditional far branch for destinations encodable in 24+2 bits. + // Same interface as bc, e.g. no inverse boint-field. + enum { + bc_far_optimize_not = 0, + bc_far_optimize_on_relocate = 1 + }; + // optimize: flag for telling the conditional far branch to optimize + // itself when relocated. + void bc_far(int boint, int biint, Label& dest, int optimize); + // Relocation of conditional far branches. + static bool is_bc_far_at(address instruction_addr); + static address get_dest_of_bc_far_at(address instruction_addr); + static void set_dest_of_bc_far_at(address instruction_addr, address dest); + private: + static bool inline is_bc_far_variant1_at(address instruction_addr); + static bool inline is_bc_far_variant2_at(address instruction_addr); + static bool inline is_bc_far_variant3_at(address instruction_addr); + public: + + // Convenience bc_far versions. + inline void blt_far(ConditionRegister crx, Label& L, int optimize); + inline void bgt_far(ConditionRegister crx, Label& L, int optimize); + inline void beq_far(ConditionRegister crx, Label& L, int optimize); + inline void bso_far(ConditionRegister crx, Label& L, int optimize); + inline void bge_far(ConditionRegister crx, Label& L, int optimize); + inline void ble_far(ConditionRegister crx, Label& L, int optimize); + inline void bne_far(ConditionRegister crx, Label& L, int optimize); + inline void bns_far(ConditionRegister crx, Label& L, int optimize); + + // Emit, identify and patch a NOT mt-safe patchable 64 bit absolute call/jump. + private: + enum { + bxx64_patchable_instruction_count = (2/*load_codecache_const*/ + 3/*5load_const*/ + 1/*mtctr*/ + 1/*bctrl*/), + bxx64_patchable_size = bxx64_patchable_instruction_count * BytesPerInstWord, + bxx64_patchable_ret_addr_offset = bxx64_patchable_size + }; + void bxx64_patchable(address target, relocInfo::relocType rt, bool link); + static bool is_bxx64_patchable_at( address instruction_addr, bool link); + // Does the instruction use a pc-relative encoding of the destination? + static bool is_bxx64_patchable_pcrelative_at( address instruction_addr, bool link); + static bool is_bxx64_patchable_variant1_at( address instruction_addr, bool link); + // Load destination relative to global toc. + static bool is_bxx64_patchable_variant1b_at( address instruction_addr, bool link); + static bool is_bxx64_patchable_variant2_at( address instruction_addr, bool link); + static void set_dest_of_bxx64_patchable_at( address instruction_addr, address target, bool link); + static address get_dest_of_bxx64_patchable_at(address instruction_addr, bool link); + + public: + // call + enum { + bl64_patchable_instruction_count = bxx64_patchable_instruction_count, + bl64_patchable_size = bxx64_patchable_size, + bl64_patchable_ret_addr_offset = bxx64_patchable_ret_addr_offset + }; + inline void bl64_patchable(address target, relocInfo::relocType rt) { + bxx64_patchable(target, rt, /*link=*/true); + } + inline static bool is_bl64_patchable_at(address instruction_addr) { + return is_bxx64_patchable_at(instruction_addr, /*link=*/true); + } + inline static bool is_bl64_patchable_pcrelative_at(address instruction_addr) { + return is_bxx64_patchable_pcrelative_at(instruction_addr, /*link=*/true); + } + inline static void set_dest_of_bl64_patchable_at(address instruction_addr, address target) { + set_dest_of_bxx64_patchable_at(instruction_addr, target, /*link=*/true); + } + inline static address get_dest_of_bl64_patchable_at(address instruction_addr) { + return get_dest_of_bxx64_patchable_at(instruction_addr, /*link=*/true); + } + // jump + enum { + b64_patchable_instruction_count = bxx64_patchable_instruction_count, + b64_patchable_size = bxx64_patchable_size, + }; + inline void b64_patchable(address target, relocInfo::relocType rt) { + bxx64_patchable(target, rt, /*link=*/false); + } + inline static bool is_b64_patchable_at(address instruction_addr) { + return is_bxx64_patchable_at(instruction_addr, /*link=*/false); + } + inline static bool is_b64_patchable_pcrelative_at(address instruction_addr) { + return is_bxx64_patchable_pcrelative_at(instruction_addr, /*link=*/false); + } + inline static void set_dest_of_b64_patchable_at(address instruction_addr, address target) { + set_dest_of_bxx64_patchable_at(instruction_addr, target, /*link=*/false); + } + inline static address get_dest_of_b64_patchable_at(address instruction_addr) { + return get_dest_of_bxx64_patchable_at(instruction_addr, /*link=*/false); + } + + // + // Support for frame handling + // + + // some ABI-related functions + void save_nonvolatile_gprs( Register dst_base, int offset); + void restore_nonvolatile_gprs(Register src_base, int offset); + void save_volatile_gprs( Register dst_base, int offset); + void restore_volatile_gprs(Register src_base, int offset); + void save_LR_CR( Register tmp); // tmp contains LR on return. + void restore_LR_CR(Register tmp); + + // Get current PC using bl-next-instruction trick. + address get_PC_trash_LR(Register result); + + // Resize current frame either relatively wrt to current SP or absolute. + void resize_frame(Register offset, Register tmp); + void resize_frame(int offset, Register tmp); + void resize_frame_absolute(Register addr, Register tmp1, Register tmp2); + + // Push a frame of size bytes. + void push_frame(Register bytes, Register tmp); + + // Push a frame of size `bytes'. No abi space provided. + void push_frame(unsigned int bytes, Register tmp); + + // Push a frame of size `bytes' plus abi112 on top. + void push_frame_abi112(unsigned int bytes, Register tmp); + + // Setup up a new C frame with a spill area for non-volatile GPRs and additional + // space for local variables + void push_frame_abi112_nonvolatiles(unsigned int bytes, Register tmp); + + // pop current C frame + void pop_frame(); + + // + // Calls + // + + private: + address _last_calls_return_pc; + + // Generic version of a call to C function via a function descriptor + // with variable support for C calling conventions (TOC, ENV, etc.). + // updates and returns _last_calls_return_pc. + address branch_to(Register function_descriptor, bool and_link, bool save_toc_before_call, + bool restore_toc_after_call, bool load_toc_of_callee, bool load_env_of_callee); + + public: + + // Get the pc where the last call will return to. returns _last_calls_return_pc. + inline address last_calls_return_pc(); + + // Call a C function via a function descriptor and use full C + // calling conventions. Updates and returns _last_calls_return_pc. + address call_c(Register function_descriptor); + address call_c(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt); + address call_c_using_toc(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt, + Register toc); + + protected: + + // It is imperative that all calls into the VM are handled via the + // call_VM macros. They make sure that the stack linkage is setup + // correctly. call_VM's correspond to ENTRY/ENTRY_X entry points + // while call_VM_leaf's correspond to LEAF entry points. + // + // This is the base routine called by the different versions of + // call_VM. The interpreter may customize this version by overriding + // it for its purposes (e.g., to save/restore additional registers + // when doing a VM call). + // + // If no last_java_sp is specified (noreg) then SP will be used instead. + virtual void call_VM_base( + // where an oop-result ends up if any; use noreg otherwise + Register oop_result, + // to set up last_Java_frame in stubs; use noreg otherwise + Register last_java_sp, + // the entry point + address entry_point, + // flag which indicates if exception should be checked + bool check_exception=true + ); + + // Support for VM calls. This is the base routine called by the + // different versions of call_VM_leaf. The interpreter may customize + // this version by overriding it for its purposes (e.g., to + // save/restore additional registers when doing a VM call). + void call_VM_leaf_base(address entry_point); + + public: + // Call into the VM. + // Passes the thread pointer (in R3_ARG1) as a prepended argument. + // Makes sure oop return values are visible to the GC. + void call_VM(Register oop_result, address entry_point, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void call_VM_leaf(address entry_point); + void call_VM_leaf(address entry_point, Register arg_1); + void call_VM_leaf(address entry_point, Register arg_1, Register arg_2); + void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); + + // Call a stub function via a function descriptor, but don't save + // TOC before call, don't setup TOC and ENV for call, and don't + // restore TOC after call. Updates and returns _last_calls_return_pc. + inline address call_stub(Register function_entry); + inline void call_stub_and_return_to(Register function_entry, Register return_pc); + + // + // Java utilities + // + + // Read from the polling page, its address is already in a register. + inline void load_from_polling_page(Register polling_page_address, int offset = 0); + // Check whether instruction is a read access to the polling page + // which was emitted by load_from_polling_page(..). + static bool is_load_from_polling_page(int instruction, void* ucontext/*may be NULL*/, + address* polling_address_ptr = NULL); + + // Check whether instruction is a write access to the memory + // serialization page realized by one of the instructions stw, stwu, + // stwx, or stwux. + static bool is_memory_serialization(int instruction, JavaThread* thread, void* ucontext); + + // Support for NULL-checks + // + // Generates code that causes a NULL OS exception if the content of reg is NULL. + // If the accessed location is M[reg + offset] and the offset is known, provide the + // offset. No explicit code generation is needed if the offset is within a certain + // range (0 <= offset <= page_size). + + // Stack overflow checking + void bang_stack_with_offset(int offset); + + // If instruction is a stack bang of the form ld, stdu, or + // stdux, return the banged address. Otherwise, return 0. + static address get_stack_bang_address(int instruction, void* ucontext); + + // Atomics + // CmpxchgX sets condition register to cmpX(current, compare). + // (flag == ne) => (dest_current_value != compare_value), (!swapped) + // (flag == eq) => (dest_current_value == compare_value), ( swapped) + static inline bool cmpxchgx_hint_acquire_lock() { return true; } + // The stxcx will probably not be succeeded by a releasing store. + static inline bool cmpxchgx_hint_release_lock() { return false; } + static inline bool cmpxchgx_hint_atomic_update() { return false; } + + // Cmpxchg semantics + enum { + MemBarNone = 0, + MemBarRel = 1, + MemBarAcq = 2, + MemBarFenceAfter = 4 // use powers of 2 + }; + void cmpxchgw(ConditionRegister flag, + Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base, + int semantics, bool cmpxchgx_hint = false, + Register int_flag_success = noreg, bool contention_hint = false); + void cmpxchgd(ConditionRegister flag, + Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base, + int semantics, bool cmpxchgx_hint = false, + Register int_flag_success = noreg, Label* failed = NULL, bool contention_hint = false); + + // interface method calling + void lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register temp_reg, Register temp2_reg, + Label& no_such_interface); + + // virtual method calling + void lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result); + + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except temp_reg and temp2_reg. + // If super_check_offset is not -1, temp2_reg is not used and can be noreg. + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label& L_success, + Label& L_failure); + + // The rest of the type check; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The temp_reg can be noreg, if no temps are available. + // It can also be sub_klass or super_klass, meaning it's OK to kill that one. + // Updates the sub's secondary super cache as necessary. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label* L_success = NULL, + Register result_reg = noreg); + + // Simplified, combined version, good for typical uses. + // Falls through on failure. + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp1_reg, + Register temp2_reg, + Label& L_success); + + // Method handle support (JSR 292). + void check_method_handle_type(Register mtype_reg, Register mh_reg, Register temp_reg, Label& wrong_method_type); + + RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, Register temp_reg, int extra_slot_offset = 0); + + // Biased locking support + // Upon entry,obj_reg must contain the target object, and mark_reg + // must contain the target object's header. + // Destroys mark_reg if an attempt is made to bias an anonymously + // biased lock. In this case a failure will go either to the slow + // case or fall through with the notEqual condition code set with + // the expectation that the slow case in the runtime will be called. + // In the fall-through case where the CAS-based lock is done, + // mark_reg is not destroyed. + void biased_locking_enter(ConditionRegister cr_reg, Register obj_reg, Register mark_reg, Register temp_reg, + Register temp2_reg, Label& done, Label* slow_case = NULL); + // Upon entry, the base register of mark_addr must contain the oop. + // Destroys temp_reg. + // If allow_delay_slot_filling is set to true, the next instruction + // emitted after this one will go in an annulled delay slot if the + // biased locking exit case failed. + void biased_locking_exit(ConditionRegister cr_reg, Register mark_addr, Register temp_reg, Label& done); + + void compiler_fast_lock_object( ConditionRegister flag, Register oop, Register box, Register tmp1, Register tmp2, Register tmp3); + void compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box, Register tmp1, Register tmp2, Register tmp3); + + // Support for serializing memory accesses between threads + void serialize_memory(Register thread, Register tmp1, Register tmp2); + + // GC barrier support. + void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp); + void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj); + +#ifndef SERIALGC + // General G1 pre-barrier generator. + void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, + Register Rtmp1, Register Rtmp2, bool needs_frame = false); + // General G1 post-barrier generator + void g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1, + Register Rtmp2, Register Rtmp3, Label *filtered_ext = NULL); +#endif // SERIALGC + + // Support for managing the JavaThread pointer (i.e.; the reference to + // thread-local information). + + // Support for last Java frame (but use call_VM instead where possible): + // access R16_thread->last_Java_sp. + void set_last_Java_frame(Register last_java_sp, Register last_Java_pc); + void reset_last_Java_frame(void); + void set_top_ijava_frame_at_SP_as_last_Java_frame(Register sp, Register tmp1); + + // Read vm result from thread: oop_result = R16_thread->result; + void get_vm_result (Register oop_result); + void get_vm_result_2(Register metadata_result); + + static bool needs_explicit_null_check(intptr_t offset); + + // Trap-instruction-based checks. + // Range checks can be distinguished from zero checks as they check 32 bit, + // zero checks all 64 bits (tw, td). + inline void trap_null_check(Register a, trap_to_bits cmp = traptoEqual); + static bool is_trap_null_check(int x) { + return is_tdi(x, traptoEqual, -1/*any reg*/, 0) || + is_tdi(x, traptoGreaterThanUnsigned, -1/*any reg*/, 0); + } + + inline void trap_zombie_not_entrant(); + static bool is_trap_zombie_not_entrant(int x) { return is_tdi(x, traptoUnconditional, 0/*reg 0*/, 1); } + + inline void trap_should_not_reach_here(); + static bool is_trap_should_not_reach_here(int x) { return is_tdi(x, traptoUnconditional, 0/*reg 0*/, 2); } + + inline void trap_ic_miss_check(Register a, Register b); + static bool is_trap_ic_miss_check(int x) { + return is_td(x, traptoGreaterThanUnsigned | traptoLessThanUnsigned, -1/*any reg*/, -1/*any reg*/); + } + + // Implicit or explicit null check, jumps to static address exception_entry. + inline void null_check_throw(Register a, int offset, Register temp_reg, address exception_entry); + + // Check accessed object for null. Use SIGTRAP-based null checks on AIX. + inline void ld_with_trap_null_check(Register d, int si16, Register s1); + // Variant for heap OOPs including decompression of compressed OOPs. + inline void load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant offs, Register s1); + + // Load heap oop and decompress. Loaded oop may not be null. + inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg); + + // Null allowed. + inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg); + + // Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong. + inline void encode_heap_oop_not_null(Register d); + inline void decode_heap_oop_not_null(Register d); + + // Null allowed. + inline void decode_heap_oop(Register d); + + // Load/Store klass oop from klass field. Compress. + void load_klass(Register dst, Register src); + void load_klass_with_trap_null_check(Register dst, Register src); + void store_klass(Register dst_oop, Register klass, Register tmp = R0); + void decode_klass_not_null(Register dst, Register src = noreg); + void encode_klass_not_null(Register dst, Register src = noreg); + + // Load common heap base into register. + void reinit_heapbase(Register d, Register tmp = noreg); + + // SIGTRAP-based range checks for arrays. + inline void trap_range_check_l(Register a, Register b); + inline void trap_range_check_l(Register a, int si16); + static bool is_trap_range_check_l(int x) { + return (is_tw (x, traptoLessThanUnsigned, -1/*any reg*/, -1/*any reg*/) || + is_twi(x, traptoLessThanUnsigned, -1/*any reg*/) ); + } + inline void trap_range_check_le(Register a, int si16); + static bool is_trap_range_check_le(int x) { + return is_twi(x, traptoEqual | traptoLessThanUnsigned, -1/*any reg*/); + } + inline void trap_range_check_g(Register a, int si16); + static bool is_trap_range_check_g(int x) { + return is_twi(x, traptoGreaterThanUnsigned, -1/*any reg*/); + } + inline void trap_range_check_ge(Register a, Register b); + inline void trap_range_check_ge(Register a, int si16); + static bool is_trap_range_check_ge(int x) { + return (is_tw (x, traptoEqual | traptoGreaterThanUnsigned, -1/*any reg*/, -1/*any reg*/) || + is_twi(x, traptoEqual | traptoGreaterThanUnsigned, -1/*any reg*/) ); + } + static bool is_trap_range_check(int x) { + return is_trap_range_check_l(x) || is_trap_range_check_le(x) || + is_trap_range_check_g(x) || is_trap_range_check_ge(x); + } + + // Needle of length 1. + void string_indexof_1(Register result, Register haystack, Register haycnt, + Register needle, jchar needleChar, + Register tmp1, Register tmp2); + // General indexof, eventually with constant needle length. + void string_indexof(Register result, Register haystack, Register haycnt, + Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval, + Register tmp1, Register tmp2, Register tmp3, Register tmp4); + void string_compare(Register str1_reg, Register str2_reg, Register cnt1_reg, Register cnt2_reg, + Register result_reg, Register tmp_reg); + void char_arrays_equals(Register str1_reg, Register str2_reg, Register cnt_reg, Register result_reg, + Register tmp1_reg, Register tmp2_reg, Register tmp3_reg, Register tmp4_reg, + Register tmp5_reg); + void char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg, + Register tmp1_reg, Register tmp2_reg); + + // + // Debugging + // + + // assert on cr0 + void asm_assert(bool check_equal, const char* msg, int id); + void asm_assert_eq(const char* msg, int id) { asm_assert(true, msg, id); } + void asm_assert_ne(const char* msg, int id) { asm_assert(false, msg, id); } + + private: + void asm_assert_mems_zero(bool check_equal, int size, int mem_offset, Register mem_base, + const char* msg, int id); + + public: + + void asm_assert_mem8_is_zero(int mem_offset, Register mem_base, const char* msg, int id) { + asm_assert_mems_zero(true, 8, mem_offset, mem_base, msg, id); + } + void asm_assert_mem8_isnot_zero(int mem_offset, Register mem_base, const char* msg, int id) { + asm_assert_mems_zero(false, 8, mem_offset, mem_base, msg, id); + } + + // Verify R16_thread contents. + void verify_thread(); + + // Emit code to verify that reg contains a valid oop if +VerifyOops is set. + void verify_oop(Register reg, const char* s = "broken oop"); + + // TODO: verify method and klass metadata (compare against vptr?) + void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} + void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} + +#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) +#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) + + private: + + enum { + stop_stop = 0, + stop_untested = 1, + stop_unimplemented = 2, + stop_shouldnotreachhere = 3, + stop_end = 4 + }; + void stop(int type, const char* msg, int id); + + public: + // Prints msg, dumps registers and stops execution. + void stop (const char* msg = "", int id = 0) { stop(stop_stop, msg, id); } + void untested (const char* msg = "", int id = 0) { stop(stop_untested, msg, id); } + void unimplemented(const char* msg = "", int id = 0) { stop(stop_unimplemented, msg, id); } + void should_not_reach_here() { stop(stop_shouldnotreachhere, "", -1); } + + void zap_from_to(Register low, int before, Register high, int after, Register val, Register addr) PRODUCT_RETURN; +}; + +#endif // CPU_PPC_VM_MACROASSEMBLER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp new file mode 100644 index 00000000000..d80e4ec4459 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP +#define CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP + +#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + +inline bool MacroAssembler::is_ld_largeoffset(address a) { + const int inst1 = *(int *)a; + const int inst2 = *(int *)(a+4); + return (is_ld(inst1)) || + (is_addis(inst1) && is_ld(inst2) && inv_ra_field(inst2) == inv_rt_field(inst1)); +} + +inline int MacroAssembler::get_ld_largeoffset_offset(address a) { + assert(MacroAssembler::is_ld_largeoffset(a), "must be ld with large offset"); + + const int inst1 = *(int *)a; + if (is_ld(inst1)) { + return inv_d1_field(inst1); + } else { + const int inst2 = *(int *)(a+4); + return (inv_d1_field(inst1) << 16) + inv_d1_field(inst2); + } +} + +inline void MacroAssembler::round_to(Register r, int modulus) { + assert(is_power_of_2_long((jlong)modulus), "must be power of 2"); + addi(r, r, modulus-1); + clrrdi(r, r, log2_long((jlong)modulus)); +} + +// Move register if destination register and target register are different. +inline void MacroAssembler::mr_if_needed(Register rd, Register rs) { + if(rs !=rd) mr(rd, rs); +} + +// Address of the global TOC. +inline address MacroAssembler::global_toc() { + return CodeCache::low_bound(); +} + +// Offset of given address to the global TOC. +inline int MacroAssembler::offset_to_global_toc(const address addr) { + intptr_t offset = (intptr_t)addr - (intptr_t)MacroAssembler::global_toc(); + assert(Assembler::is_simm((long)offset, 31) && offset >= 0, "must be in range"); + return (int)offset; +} + +// Address of current method's TOC. +inline address MacroAssembler::method_toc() { + return code()->consts()->start(); +} + +// Offset of given address to current method's TOC. +inline int MacroAssembler::offset_to_method_toc(address addr) { + intptr_t offset = (intptr_t)addr - (intptr_t)method_toc(); + assert(is_simm((long)offset, 31) && offset >= 0, "must be in range"); + return (int)offset; +} + +inline bool MacroAssembler::is_calculate_address_from_global_toc_at(address a, address bound) { + const address inst2_addr = a; + const int inst2 = *(int *) a; + + // The relocation points to the second instruction, the addi. + if (!is_addi(inst2)) return false; + + // The addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + if (inv_ra_field(inst2) != dst) return false; + + // Now, find the preceding addis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + while (inst1_addr >= bound) { + inst1 = *(int *) inst1_addr; + if (is_addis(inst1) && inv_rt_field(inst1) == dst) { + // stop, found the addis which writes dst + break; + } + inst1_addr -= BytesPerInstWord; + } + + if (!(inst1 == 0 || inv_ra_field(inst1) == 29 /* R29 */)) return false; + return is_addis(inst1); +} + +#ifdef _LP64 +// Detect narrow oop constants. +inline bool MacroAssembler::is_set_narrow_oop(address a, address bound) { + const address inst2_addr = a; + const int inst2 = *(int *)a; + + // The relocation points to the second instruction, the addi. + if (!is_addi(inst2)) return false; + + // The addi reads and writes the same register dst. + const int dst = inv_rt_field(inst2); + if (inv_ra_field(inst2) != dst) return false; + + // Now, find the preceding addis which writes to dst. + int inst1 = 0; + address inst1_addr = inst2_addr - BytesPerInstWord; + while (inst1_addr >= bound) { + inst1 = *(int *) inst1_addr; + if (is_lis(inst1) && inv_rs_field(inst1) == dst) return true; + inst1_addr -= BytesPerInstWord; + } + return false; +} +#endif + + +inline bool MacroAssembler::is_load_const_at(address a) { + const int* p_inst = (int *) a; + bool b = is_lis(*p_inst++); + if (is_ori(*p_inst)) { + p_inst++; + b = b && is_rldicr(*p_inst++); // TODO: could be made more precise: `sldi'! + b = b && is_oris(*p_inst++); + b = b && is_ori(*p_inst); + } else if (is_lis(*p_inst)) { + p_inst++; + b = b && is_ori(*p_inst++); + b = b && is_ori(*p_inst); + // TODO: could enhance reliability by adding is_insrdi + } else return false; + return b; +} + +inline void MacroAssembler::set_oop_constant(jobject obj, Register d) { + set_oop(constant_oop_address(obj), d); +} + +inline void MacroAssembler::set_oop(AddressLiteral obj_addr, Register d) { + assert(obj_addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc"); + load_const(d, obj_addr); +} + +inline void MacroAssembler::pd_patch_instruction(address branch, address target) { + jint& stub_inst = *(jint*) branch; + stub_inst = patched_branch(target - branch, stub_inst, 0); +} + +// Relocation of conditional far branches. +inline bool MacroAssembler::is_bc_far_variant1_at(address instruction_addr) { + // Variant 1, the 1st instruction contains the destination address: + // + // bcxx DEST + // endgroup + // + const int instruction_1 = *(int*)(instruction_addr); + const int instruction_2 = *(int*)(instruction_addr + 4); + return is_bcxx(instruction_1) && + (inv_bd_field(instruction_1, (intptr_t)instruction_addr) != (intptr_t)(instruction_addr + 2*4)) && + is_endgroup(instruction_2); +} + +// Relocation of conditional far branches. +inline bool MacroAssembler::is_bc_far_variant2_at(address instruction_addr) { + // Variant 2, the 2nd instruction contains the destination address: + // + // b!cxx SKIP + // bxx DEST + // SKIP: + // + const int instruction_1 = *(int*)(instruction_addr); + const int instruction_2 = *(int*)(instruction_addr + 4); + return is_bcxx(instruction_1) && + (inv_bd_field(instruction_1, (intptr_t)instruction_addr) == (intptr_t)(instruction_addr + 2*4)) && + is_bxx(instruction_2); +} + +// Relocation for conditional branches +inline bool MacroAssembler::is_bc_far_variant3_at(address instruction_addr) { + // Variant 3, far cond branch to the next instruction, already patched to nops: + // + // nop + // endgroup + // SKIP/DEST: + // + const int instruction_1 = *(int*)(instruction_addr); + const int instruction_2 = *(int*)(instruction_addr + 4); + return is_nop(instruction_1) && + is_endgroup(instruction_2); +} + + +// Convenience bc_far versions +inline void MacroAssembler::blt_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, less), L, optimize); } +inline void MacroAssembler::bgt_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, greater), L, optimize); } +inline void MacroAssembler::beq_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, equal), L, optimize); } +inline void MacroAssembler::bso_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, summary_overflow), L, optimize); } +inline void MacroAssembler::bge_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, less), L, optimize); } +inline void MacroAssembler::ble_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, greater), L, optimize); } +inline void MacroAssembler::bne_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, equal), L, optimize); } +inline void MacroAssembler::bns_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, summary_overflow), L, optimize); } + +inline address MacroAssembler::call_stub(Register function_entry) { + mtctr(function_entry); + bctrl(); + return pc(); +} + +inline void MacroAssembler::call_stub_and_return_to(Register function_entry, Register return_pc) { + assert_different_registers(function_entry, return_pc); + mtlr(return_pc); + mtctr(function_entry); + bctr(); +} + +// Get the pc where the last emitted call will return to. +inline address MacroAssembler::last_calls_return_pc() { + return _last_calls_return_pc; +} + +// Read from the polling page, its address is already in a register. +inline void MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) { + ld(R0, offset, polling_page_address); +} + +// Trap-instruction-based checks. + +inline void MacroAssembler::trap_null_check(Register a, trap_to_bits cmp) { + assert(TrapBasedNullChecks, "sanity"); + tdi(cmp, a/*reg a*/, 0); +} +inline void MacroAssembler::trap_zombie_not_entrant() { + tdi(traptoUnconditional, 0/*reg 0*/, 1); +} +inline void MacroAssembler::trap_should_not_reach_here() { + tdi_unchecked(traptoUnconditional, 0/*reg 0*/, 2); +} + +inline void MacroAssembler::trap_ic_miss_check(Register a, Register b) { + td(traptoGreaterThanUnsigned | traptoLessThanUnsigned, a, b); +} + +// Do an explicit null check if access to a+offset will not raise a SIGSEGV. +// Either issue a trap instruction that raises SIGTRAP, or do a compare that +// branches to exception_entry. +// No support for compressed oops (base page of heap). Does not distinguish +// loads and stores. +inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, address exception_entry) { + if (!ImplicitNullChecks || needs_explicit_null_check(offset) NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + assert(UseSIGTRAP, "sanity"); + trap_null_check(a); + } else { + Label ok; + cmpdi(CCR0, a, 0); + bne(CCR0, ok); + load_const_optimized(temp_reg, exception_entry); + mtctr(temp_reg); + bctr(); + bind(ok); + } + } +} + +inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Register s1) { + if ( NOT_LINUX(true) LINUX_ONLY(false)/*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + trap_null_check(s1); + } + } + ld(d, si16, s1); +} + +// Attention: No null check for loaded uncompressed OOP. Can be used for loading klass field. +inline void MacroAssembler::load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant si16, + Register s1) { + if ( NOT_LINUX(true)LINUX_ONLY(false) /*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + trap_null_check(s1); + } + } + load_heap_oop_not_null(d, si16, s1); +} + +inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) { + if (UseCompressedOops) { + lwz(d, offs, s1); + // Attention: no null check here! + decode_heap_oop_not_null(d); + } else { + ld(d, offs, s1); + } +} + +inline void MacroAssembler::load_heap_oop(Register d, RegisterOrConstant offs, Register s1) { + if (UseCompressedOops) { + lwz(d, offs, s1); + decode_heap_oop(d); + } else { + ld(d, offs, s1); + } +} + +inline void MacroAssembler::encode_heap_oop_not_null(Register d) { + if (Universe::narrow_oop_base() != NULL) { + sub(d, d, R30); + } + if (Universe::narrow_oop_shift() != 0) { + srdi(d, d, LogMinObjAlignmentInBytes); + } +} + +inline void MacroAssembler::decode_heap_oop_not_null(Register d) { + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + sldi(d, d, LogMinObjAlignmentInBytes); + } + if (Universe::narrow_oop_base() != NULL) { + add(d, d, R30); + } +} + +inline void MacroAssembler::decode_heap_oop(Register d) { + Label isNull; + if (Universe::narrow_oop_base() != NULL) { + cmpwi(CCR0, d, 0); + beq(CCR0, isNull); + } + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + sldi(d, d, LogMinObjAlignmentInBytes); + } + if (Universe::narrow_oop_base() != NULL) { + add(d, d, R30); + } + bind(isNull); +} + +// SIGTRAP-based range checks for arrays. +inline void MacroAssembler::trap_range_check_l(Register a, Register b) { + tw (traptoLessThanUnsigned, a/*reg a*/, b/*reg b*/); +} +inline void MacroAssembler::trap_range_check_l(Register a, int si16) { + twi(traptoLessThanUnsigned, a/*reg a*/, si16); +} +inline void MacroAssembler::trap_range_check_le(Register a, int si16) { + twi(traptoEqual | traptoLessThanUnsigned, a/*reg a*/, si16); +} +inline void MacroAssembler::trap_range_check_g(Register a, int si16) { + twi(traptoGreaterThanUnsigned, a/*reg a*/, si16); +} +inline void MacroAssembler::trap_range_check_ge(Register a, Register b) { + tw (traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, b/*reg b*/); +} +inline void MacroAssembler::trap_range_check_ge(Register a, int si16) { + twi(traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, si16); +} + +#endif // CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP diff --git a/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp b/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp new file mode 100644 index 00000000000..9d68ca0f79b --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/metaspaceShared_ppc.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "asm/codeBuffer.hpp" +#include "memory/metaspaceShared.hpp" + +// Generate the self-patching vtable method: +// +// This method will be called (as any other Klass virtual method) with +// the Klass itself as the first argument. Example: +// +// oop obj; +// int size = obj->klass()->klass_part()->oop_size(this); +// +// for which the virtual method call is Klass::oop_size(); +// +// The dummy method is called with the Klass object as the first +// operand, and an object as the second argument. +// + +//===================================================================== + +// All of the dummy methods in the vtable are essentially identical, +// differing only by an ordinal constant, and they bear no releationship +// to the original method which the caller intended. Also, there needs +// to be 'vtbl_list_size' instances of the vtable in order to +// differentiate between the 'vtable_list_size' original Klass objects. + +void MetaspaceShared::generate_vtable_methods(void** vtbl_list, + void** vtable, + char** md_top, + char* md_end, + char** mc_top, + char* mc_end) { + Unimplemented(); +} + diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp new file mode 100644 index 00000000000..f145e8c6d7d --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -0,0 +1,540 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/allocation.inline.hpp" +#include "prims/methodHandles.hpp" + +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#define STOP(error) stop(error) +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#define STOP(error) block_comment(error); __ stop(error) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. +inline static RegisterOrConstant constant(int value) { + return RegisterOrConstant(value); +} + +void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg, Register temp_reg, Register temp2_reg) { + if (VerifyMethodHandles) + verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class), temp_reg, temp2_reg, + "MH argument is a Class"); + __ ld(klass_reg, java_lang_Class::klass_offset_in_bytes(), klass_reg); +} + +#ifdef ASSERT +static int check_nonzero(const char* xname, int x) { + assert(x != 0, err_msg("%s should be nonzero", xname)); + return x; +} +#define NONZERO(x) check_nonzero(#x, x) +#else //ASSERT +#define NONZERO(x) (x) +#endif //ASSERT + +#ifdef ASSERT +void MethodHandles::verify_klass(MacroAssembler* _masm, + Register obj_reg, SystemDictionary::WKID klass_id, + Register temp_reg, Register temp2_reg, + const char* error_message) { + Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); + KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Label L_ok, L_bad; + BLOCK_COMMENT("verify_klass {"); + __ verify_oop(obj_reg); + __ cmpdi(CCR0, obj_reg, 0); + __ beq(CCR0, L_bad); + __ load_klass(temp_reg, obj_reg); + __ load_const_optimized(temp2_reg, (address) klass_addr); + __ ld(temp2_reg, 0, temp2_reg); + __ cmpd(CCR0, temp_reg, temp2_reg); + __ beq(CCR0, L_ok); + __ ld(temp_reg, klass->super_check_offset(), temp_reg); + __ cmpd(CCR0, temp_reg, temp2_reg); + __ beq(CCR0, L_ok); + __ BIND(L_bad); + __ stop(error_message); + __ BIND(L_ok); + BLOCK_COMMENT("} verify_klass"); +} + +void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) { + Label L; + BLOCK_COMMENT("verify_ref_kind {"); + __ load_sized_value(temp, NONZERO(java_lang_invoke_MemberName::flags_offset_in_bytes()), member_reg, + sizeof(u4), /*is_signed*/ false); + // assert(sizeof(u4) == sizeof(java.lang.invoke.MemberName.flags), ""); + __ srwi( temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT); + __ andi(temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK); + __ cmpwi(CCR1, temp, ref_kind); + __ beq(CCR1, L); + { char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal); + jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind); + if (ref_kind == JVM_REF_invokeVirtual || + ref_kind == JVM_REF_invokeSpecial) + // could do this for all ref_kinds, but would explode assembly code size + trace_method_handle(_masm, buf); + __ stop(buf); + } + BLOCK_COMMENT("} verify_ref_kind"); + __ BIND(L); +} + +#endif // ASSERT + +void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp, + bool for_compiler_entry) { + assert(method == R19_method, "interpreter calling convention"); + assert_different_registers(method, target, temp); + + if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { + Label run_compiled_code; + // JVMTI events, such as single-stepping, are implemented partly by avoiding running + // compiled code in threads for which the event is enabled. Check here for + // interp_only_mode if these events CAN be enabled. + __ verify_thread(); + __ lwz(temp, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); + __ cmplwi(CCR0, temp, 0); + __ beq(CCR0, run_compiled_code); + __ ld(target, in_bytes(Method::interpreter_entry_offset()), R19_method); + __ mtctr(target); + __ bctr(); + __ BIND(run_compiled_code); + } + + const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : + Method::from_interpreted_offset(); + __ ld(target, in_bytes(entry_offset), R19_method); + __ mtctr(target); + __ bctr(); +} + + +void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, + Register recv, Register method_temp, + Register temp2, Register temp3, + bool for_compiler_entry) { + BLOCK_COMMENT("jump_to_lambda_form {"); + // This is the initial entry point of a lazy method handle. + // After type checking, it picks up the invoker from the LambdaForm. + assert_different_registers(recv, method_temp, temp2); // temp3 is only passed on + assert(method_temp == R19_method, "required register for loading method"); + + // Load the invoker, as MH -> MH.form -> LF.vmentry + __ verify_oop(recv); + __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv); + __ verify_oop(method_temp); + __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp); + __ verify_oop(method_temp); + // the following assumes that a Method* is normally compressed in the vmtarget field: + __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp); + + if (VerifyMethodHandles && !for_compiler_entry) { + // make sure recv is already on stack + __ ld(temp2, in_bytes(Method::const_offset()), method_temp); + __ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2, + sizeof(u2), /*is_signed*/ false); + // assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), ""); + Label L; + __ ld(temp2, __ argument_offset(temp2, temp2, 0), R17_tos); + __ cmpd(CCR1, temp2, recv); + __ beq(CCR1, L); + __ stop("receiver not on stack"); + __ BIND(L); + } + + jump_from_method_handle(_masm, method_temp, temp2, temp3, for_compiler_entry); + BLOCK_COMMENT("} jump_to_lambda_form"); +} + + + +// Code generation +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm, + vmIntrinsics::ID iid) { + const bool not_for_compiler_entry = false; // this is the interpreter entry + assert(is_signature_polymorphic(iid), "expected invoke iid"); + if (iid == vmIntrinsics::_invokeGeneric || + iid == vmIntrinsics::_compiledLambdaForm) { + // Perhaps surprisingly, the symbolic references visible to Java are not directly used. + // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod. + // They all allow an appendix argument. + __ stop("Should not reach here"); // empty stubs make SG sick + return NULL; + } + + Register argbase = R17_tos; // parameter (preserved) + Register argslot = R3; + Register temp1 = R6; + Register param_size = R7; + + // here's where control starts out: + __ align(CodeEntryAlignment); + address entry_point = __ pc(); + + if (VerifyMethodHandles) { + Label L; + BLOCK_COMMENT("verify_intrinsic_id {"); + __ load_sized_value(temp1, Method::intrinsic_id_offset_in_bytes(), R19_method, + sizeof(u1), /*is_signed*/ false); + // assert(sizeof(u1) == sizeof(Method::_intrinsic_id), ""); + __ cmpwi(CCR1, temp1, (int) iid); + __ beq(CCR1, L); + if (iid == vmIntrinsics::_linkToVirtual || + iid == vmIntrinsics::_linkToSpecial) { + // could do this for all kinds, but would explode assembly code size + trace_method_handle(_masm, "bad Method*:intrinsic_id"); + } + __ stop("bad Method*::intrinsic_id"); + __ BIND(L); + BLOCK_COMMENT("} verify_intrinsic_id"); + } + + // First task: Find out how big the argument list is. + int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid); + assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic"); + if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) { + __ ld(param_size, in_bytes(Method::const_offset()), R19_method); + __ load_sized_value(param_size, in_bytes(ConstMethod::size_of_parameters_offset()), param_size, + sizeof(u2), /*is_signed*/ false); + // assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), ""); + } else { + DEBUG_ONLY(param_size = noreg); + } + + Register tmp_mh = noreg; + if (!is_signature_polymorphic_static(iid)) { + __ ld(tmp_mh = temp1, __ argument_offset(param_size, param_size, 0), argbase); + DEBUG_ONLY(param_size = noreg); + } + + if (TraceMethodHandles) { + if (tmp_mh != noreg) + __ mr(R23_method_handle, tmp_mh); // make stub happy + trace_method_handle_interpreter_entry(_masm, iid); + } + + if (iid == vmIntrinsics::_invokeBasic) { + generate_method_handle_dispatch(_masm, iid, tmp_mh, noreg, not_for_compiler_entry); + + } else { + // Adjust argument list by popping the trailing MemberName argument. + Register tmp_recv = noreg; + if (MethodHandles::ref_kind_has_receiver(ref_kind)) { + // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack. + __ ld(tmp_recv = temp1, __ argument_offset(param_size, param_size, 0), argbase); + DEBUG_ONLY(param_size = noreg); + } + Register R19_member = R19_method; // MemberName ptr; incoming method ptr is dead now + __ ld(R19_member, RegisterOrConstant((intptr_t)8), argbase); + __ add(argbase, Interpreter::stackElementSize, argbase); + generate_method_handle_dispatch(_masm, iid, tmp_recv, R19_member, not_for_compiler_entry); + } + + return entry_point; +} + +void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, + vmIntrinsics::ID iid, + Register receiver_reg, + Register member_reg, + bool for_compiler_entry) { + assert(is_signature_polymorphic(iid), "expected invoke iid"); + Register temp1 = (for_compiler_entry ? R21_tmp1 : R7); + Register temp2 = (for_compiler_entry ? R22_tmp2 : R8); + Register temp3 = (for_compiler_entry ? R23_tmp3 : R9); + Register temp4 = (for_compiler_entry ? R24_tmp4 : R10); + if (receiver_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg); + if (member_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, member_reg); + + if (iid == vmIntrinsics::_invokeBasic) { + // indirect through MH.form.vmentry.vmtarget + jump_to_lambda_form(_masm, receiver_reg, R19_method, temp1, temp2, for_compiler_entry); + } else { + // The method is a member invoker used by direct method handles. + if (VerifyMethodHandles) { + // make sure the trailing argument really is a MemberName (caller responsibility) + verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(MemberName_klass), + temp1, temp2, + "MemberName required for invokeVirtual etc."); + } + + Register temp1_recv_klass = temp1; + if (iid != vmIntrinsics::_linkToStatic) { + __ verify_oop(receiver_reg); + if (iid == vmIntrinsics::_linkToSpecial) { + // Don't actually load the klass; just null-check the receiver. + __ null_check_throw(receiver_reg, 0, temp1, StubRoutines::throw_NullPointerException_at_call_entry()); + } else { + // load receiver klass itself + __ null_check_throw(receiver_reg, oopDesc::klass_offset_in_bytes(), + temp1, StubRoutines::throw_NullPointerException_at_call_entry()); + __ load_klass(temp1_recv_klass, receiver_reg); + __ verify_klass_ptr(temp1_recv_klass); + } + BLOCK_COMMENT("check_receiver {"); + // The receiver for the MemberName must be in receiver_reg. + // Check the receiver against the MemberName.clazz + if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) { + // Did not load it above... + __ load_klass(temp1_recv_klass, receiver_reg); + __ verify_klass_ptr(temp1_recv_klass); + } + if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) { + Label L_ok; + Register temp2_defc = temp2; + __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg); + load_klass_from_Class(_masm, temp2_defc, temp3, temp4); + __ verify_klass_ptr(temp2_defc); + __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok); + // If we get here, the type check failed! + __ stop("receiver class disagrees with MemberName.clazz"); + __ BIND(L_ok); + } + BLOCK_COMMENT("} check_receiver"); + } + if (iid == vmIntrinsics::_linkToSpecial || + iid == vmIntrinsics::_linkToStatic) { + DEBUG_ONLY(temp1_recv_klass = noreg); // these guys didn't load the recv_klass + } + + // Live registers at this point: + // member_reg - MemberName that was the trailing argument + // temp1_recv_klass - klass of stacked receiver, if needed + // O5_savedSP - interpreter linkage (if interpreted) + // O0..O5 - compiler arguments (if compiled) + + Label L_incompatible_class_change_error; + switch (iid) { + case vmIntrinsics::_linkToSpecial: + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); + } + __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + break; + + case vmIntrinsics::_linkToStatic: + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); + } + __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + break; + + case vmIntrinsics::_linkToVirtual: + { + // same as TemplateTable::invokevirtual, + // minus the CP setup and profiling: + + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp2); + } + + // pick out the vtable index from the MemberName, and then we can discard it: + Register temp2_index = temp2; + __ ld(temp2_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg); + + if (VerifyMethodHandles) { + Label L_index_ok; + __ cmpdi(CCR1, temp2_index, 0); + __ bge(CCR1, L_index_ok); + __ stop("no virtual index"); + __ BIND(L_index_ok); + } + + // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget + // at this point. And VerifyMethodHandles has already checked clazz, if needed. + + // get target Method* & entry point + __ lookup_virtual_method(temp1_recv_klass, temp2_index, R19_method); + break; + } + + case vmIntrinsics::_linkToInterface: + { + // same as TemplateTable::invokeinterface + // (minus the CP setup and profiling, with different argument motion) + if (VerifyMethodHandles) { + verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp2); + } + + Register temp2_intf = temp2; + __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg); + load_klass_from_Class(_masm, temp2_intf, temp3, temp4); + __ verify_klass_ptr(temp2_intf); + + Register vtable_index = R19_method; + __ ld(vtable_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg); + if (VerifyMethodHandles) { + Label L_index_ok; + __ cmpdi(CCR1, vtable_index, 0); + __ bge(CCR1, L_index_ok); + __ stop("invalid vtable index for MH.invokeInterface"); + __ BIND(L_index_ok); + } + + // given intf, index, and recv klass, dispatch to the implementation method + __ lookup_interface_method(temp1_recv_klass, temp2_intf, + // note: next two args must be the same: + vtable_index, R19_method, + temp3, temp4, + L_incompatible_class_change_error); + break; + } + + default: + fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); + break; + } + + // Live at this point: + // R19_method + // O5_savedSP (if interpreted) + + // After figuring out which concrete method to call, jump into it. + // Note that this works in the interpreter with no data motion. + // But the compiled version will require that rcx_recv be shifted out. + __ verify_method_ptr(R19_method); + jump_from_method_handle(_masm, R19_method, temp1, temp2, for_compiler_entry); + + if (iid == vmIntrinsics::_linkToInterface) { + __ BIND(L_incompatible_class_change_error); + __ load_const_optimized(temp1, StubRoutines::throw_IncompatibleClassChangeError_entry()); + __ mtctr(temp1); + __ bctr(); + } + } +} + +#ifndef PRODUCT +void trace_method_handle_stub(const char* adaptername, + oopDesc* mh, + intptr_t* entry_sp, + intptr_t* saved_regs) { + + bool has_mh = (strstr(adaptername, "/static") == NULL && + strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH + const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23"; + tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT, + adaptername, mh_reg_name, (intptr_t) mh, entry_sp); + + if (Verbose) { + tty->print_cr("Registers:"); + const int abi_offset = frame::abi_112_size / 8; + for (int i = R3->encoding(); i <= R13->encoding(); i++) { + Register r = as_Register(i); + int count = i - R3->encoding(); + // The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_112_size)). + tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[abi_offset + count]); + if ((count + 1) % 4 == 0) { + tty->cr(); + } else { + tty->print(", "); + } + } + tty->cr(); + + { + // dumping last frame with frame::describe + + JavaThread* p = JavaThread::active(); + + ResourceMark rm; + PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here + FrameValues values; + + // Note: We want to allow trace_method_handle from any call site. + // While trace_method_handle creates a frame, it may be entered + // without a PC on the stack top (e.g. not just after a call). + // Walking that frame could lead to failures due to that invalid PC. + // => carefully detect that frame when doing the stack walking + + // Current C frame + frame cur_frame = os::current_frame(); + + // Robust search of trace_calling_frame (independant of inlining). + // Assumes saved_regs comes from a pusha in the trace_calling_frame. + assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); + frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); + while (trace_calling_frame.fp() < saved_regs) { + trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); + } + + // safely create a frame and call frame::describe + intptr_t *dump_sp = trace_calling_frame.sender_sp(); + + frame dump_frame = frame(dump_sp); + dump_frame.describe(values, 1); + + values.describe(-1, saved_regs, "raw top of stack"); + + tty->print_cr("Stack layout:"); + values.print(p); + } + + if (has_mh && mh->is_oop()) { + mh->print(); + if (java_lang_invoke_MethodHandle::is_instance(mh)) { + if (java_lang_invoke_MethodHandle::form_offset_in_bytes() != 0) + java_lang_invoke_MethodHandle::form(mh)->print(); + } + } + } +} + +void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { + if (!TraceMethodHandles) return; + + BLOCK_COMMENT("trace_method_handle {"); + + int nbytes_save = 10 * 8; // 10 volatile gprs + __ save_LR_CR(R0); + __ mr(R0, R1_SP); // saved_sp + assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0"); + // push_frame_abi112 only uses R0 if nbytes_save is wider than 16 bit + __ push_frame_abi112(nbytes_save, R0); + __ save_volatile_gprs(R1_SP, frame::abi_112_size); // Except R0. + + __ load_const(R3_ARG1, (address)adaptername); + __ mr(R4_ARG2, R23_method_handle); + __ mr(R5_ARG3, R0); // saved_sp + __ mr(R6_ARG4, R1_SP); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub)); + + __ restore_volatile_gprs(R1_SP, 112); // except R0 + __ pop_frame(); + __ restore_LR_CR(R0); + + BLOCK_COMMENT("} trace_method_handle"); +} +#endif // PRODUCT diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.hpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.hpp new file mode 100644 index 00000000000..640813e7d3e --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// Platform-specific definitions for method handles. +// These definitions are inlined into class MethodHandles. + +// Adapters +//static unsigned int adapter_code_size() { +// return 32*K DEBUG_ONLY(+ 16*K) + (TraceMethodHandles ? 16*K : 0) + (VerifyMethodHandles ? 32*K : 0); +//} +enum /* platform_dependent_constants */ { + adapter_code_size = NOT_LP64(16000 DEBUG_ONLY(+ 25000)) LP64_ONLY(32000 DEBUG_ONLY(+ 150000)) +}; + +// Additional helper methods for MethodHandles code generation: +public: + static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg, Register temp_reg, Register temp2_reg); + + static void verify_klass(MacroAssembler* _masm, + Register obj_reg, SystemDictionary::WKID klass_id, + Register temp_reg, Register temp2_reg, + const char* error_message = "wrong klass") NOT_DEBUG_RETURN; + + static void verify_method_handle(MacroAssembler* _masm, Register mh_reg, + Register temp_reg, Register temp2_reg) { + Unimplemented(); + } + + static void verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) NOT_DEBUG_RETURN; + + // Similar to InterpreterMacroAssembler::jump_from_interpreted. + // Takes care of special dispatch from single stepping too. + static void jump_from_method_handle(MacroAssembler* _masm, Register method, + Register temp, Register temp2, + bool for_compiler_entry); + + static void jump_to_lambda_form(MacroAssembler* _masm, + Register recv, Register method_temp, + Register temp2, Register temp3, + bool for_compiler_entry); diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp new file mode 100644 index 00000000000..5b88284b2df --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_ppc.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/handles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/ostream.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif + +// We use an illtrap for marking a method as not_entrant or zombie iff !UseSIGTRAP +// Work around a C++ compiler bug which changes 'this' +bool NativeInstruction::is_sigill_zombie_not_entrant_at(address addr) { + assert(!UseSIGTRAP, "precondition"); + if (*(int*)addr != 0 /*illtrap*/) return false; + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); + if (cb == NULL || !cb->is_nmethod()) return false; + nmethod *nm = (nmethod *)cb; + // This method is not_entrant or zombie iff the illtrap instruction is + // located at the verified entry point. + return nm->verified_entry_point() == addr; +} + +#ifdef ASSERT +void NativeInstruction::verify() { + // Make sure code pattern is actually an instruction address. + address addr = addr_at(0); + if (addr == 0 || ((intptr_t)addr & 3) != 0) { + fatal("not an instruction address"); + } +} +#endif // ASSERT + +// Extract call destination from a NativeCall. The call might use a trampoline stub. +address NativeCall::destination() const { + address addr = (address)this; + address destination = Assembler::bxx_destination(addr); + + // Do we use a trampoline stub for this call? + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); // Else we get assertion if nmethod is zombie. + assert(cb && cb->is_nmethod(), "sanity"); + nmethod *nm = (nmethod *)cb; + if (nm->stub_contains(destination) && is_NativeCallTrampolineStub_at(destination)) { + // Yes we do, so get the destination from the trampoline stub. + const address trampoline_stub_addr = destination; + destination = NativeCallTrampolineStub_at(trampoline_stub_addr)->destination(); + } + + return destination; +} + +// Similar to replace_mt_safe, but just changes the destination. The +// important thing is that free-running threads are able to execute this +// call instruction at all times. Thus, the displacement field must be +// instruction-word-aligned. +// +// Used in the runtime linkage of calls; see class CompiledIC. +// +// Add parameter assert_lock to switch off assertion +// during code generation, where no patching lock is needed. +void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { + assert(!assert_lock || + (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()), + "concurrent code patching"); + + ResourceMark rm; + int code_size = 1 * BytesPerInstWord; + address addr_call = addr_at(0); + assert(MacroAssembler::is_bl(*(int*)addr_call), "unexpected code at call-site"); + + CodeBuffer cb(addr_call, code_size + 1); + MacroAssembler* a = new MacroAssembler(&cb); + + // Patch the call. + if (ReoptimizeCallSequences && + a->is_within_range_of_b(dest, addr_call)) { + a->bl(dest); + } else { + address trampoline_stub_addr = get_trampoline(); + + // We did not find a trampoline stub because the current codeblob + // does not provide this information. The branch will be patched + // later during a final fixup, when all necessary information is + // available. + if (trampoline_stub_addr == 0) + return; + + // Patch the constant in the call's trampoline stub. + NativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest); + + a->bl(trampoline_stub_addr); + } + ICache::invalidate_range(addr_call, code_size); +} + +address NativeCall::get_trampoline() { + address call_addr = addr_at(0); + + CodeBlob *code = CodeCache::find_blob(call_addr); + assert(code != NULL, "Could not find the containing code blob"); + + // There are no relocations available when the code gets relocated + // because of CodeBuffer expansion. + if (code->relocation_size() == 0) + return NULL; + + address bl_destination = Assembler::bxx_destination(call_addr); + if (code->content_contains(bl_destination) && + is_NativeCallTrampolineStub_at(bl_destination)) + return bl_destination; + + // If the codeBlob is not a nmethod, this is because we get here from the + // CodeBlob constructor, which is called within the nmethod constructor. + return trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); +} + +#ifdef ASSERT +void NativeCall::verify() { + address addr = addr_at(0); + + if (!NativeCall::is_call_at(addr)) { + tty->print_cr("not a NativeCall at " PTR_FORMAT, addr); + // TODO: PPC port: Disassembler::decode(addr - 20, addr + 20, tty); + fatal(err_msg("not a NativeCall at " PTR_FORMAT, addr)); + } +} +#endif // ASSERT + +#ifdef ASSERT +void NativeFarCall::verify() { + address addr = addr_at(0); + + NativeInstruction::verify(); + if (!NativeFarCall::is_far_call_at(addr)) { + tty->print_cr("not a NativeFarCall at " PTR_FORMAT, addr); + // TODO: PPC port: Disassembler::decode(addr, 20, 20, tty); + fatal(err_msg("not a NativeFarCall at " PTR_FORMAT, addr)); + } +} +#endif // ASSERT + +address NativeMovConstReg::next_instruction_address() const { +#ifdef ASSERT + CodeBlob* nm = CodeCache::find_blob(instruction_address()); + assert(!MacroAssembler::is_set_narrow_oop(addr_at(0), nm->content_begin()), "Should not patch narrow oop here"); +#endif + + if (MacroAssembler::is_load_const_from_method_toc_at(addr_at(0))) { + return addr_at(load_const_from_method_toc_instruction_size); + } else { + return addr_at(load_const_instruction_size); + } +} + +intptr_t NativeMovConstReg::data() const { + address addr = addr_at(0); + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); + + if (MacroAssembler::is_load_const_at(addr)) { + return MacroAssembler::get_const(addr); + } else if (MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) { + narrowOop no = (narrowOop)MacroAssembler::get_narrow_oop(addr, cb->content_begin()); + return (intptr_t)oopDesc::decode_heap_oop(no); + } else { + assert(MacroAssembler::is_load_const_from_method_toc_at(addr), "must be load_const_from_pool"); + + address ctable = cb->content_begin(); + int offset = MacroAssembler::get_offset_of_load_const_from_method_toc_at(addr); + return *(intptr_t *)(ctable + offset); + } +} + +address NativeMovConstReg::set_data_plain(intptr_t data, CodeBlob *cb) { + address addr = instruction_address(); + address next_address = NULL; + if (!cb) cb = CodeCache::find_blob(addr); + + if (cb != NULL && MacroAssembler::is_load_const_from_method_toc_at(addr)) { + // A load from the method's TOC (ctable). + assert(cb->is_nmethod(), "must be nmethod"); + const address ctable = cb->content_begin(); + const int toc_offset = MacroAssembler::get_offset_of_load_const_from_method_toc_at(addr); + *(intptr_t *)(ctable + toc_offset) = data; + next_address = addr + BytesPerInstWord; + } else if (cb != NULL && + MacroAssembler::is_calculate_address_from_global_toc_at(addr, cb->content_begin())) { + // A calculation relative to the global TOC. + const int invalidated_range = + MacroAssembler::patch_calculate_address_from_global_toc_at(addr, cb->content_begin(), + (address)data); + const address start = invalidated_range < 0 ? addr + invalidated_range : addr; + // FIXME: + const int range = invalidated_range < 0 ? 4 - invalidated_range : 8; + ICache::invalidate_range(start, range); + next_address = addr + 1 * BytesPerInstWord; + } else if (MacroAssembler::is_load_const_at(addr)) { + // A normal 5 instruction load_const code sequence. + // This is not mt safe, ok in methods like CodeBuffer::copy_code(). + MacroAssembler::patch_const(addr, (long)data); + ICache::invalidate_range(addr, load_const_instruction_size); + next_address = addr + 5 * BytesPerInstWord; + } else if (MacroAssembler::is_bl(* (int*) addr)) { + // A single branch-and-link instruction. + ResourceMark rm; + const int code_size = 1 * BytesPerInstWord; + CodeBuffer cb(addr, code_size + 1); + MacroAssembler* a = new MacroAssembler(&cb); + a->bl((address) data); + ICache::invalidate_range(addr, code_size); + next_address = addr + code_size; + } else { + ShouldNotReachHere(); + } + + return next_address; +} + +void NativeMovConstReg::set_data(intptr_t data) { + // Store the value into the instruction stream. + CodeBlob *cb = CodeCache::find_blob(instruction_address()); + address next_address = set_data_plain(data, cb); + + // Also store the value into an oop_Relocation cell, if any. + if (cb && cb->is_nmethod()) { + RelocIterator iter((nmethod *) cb, instruction_address(), next_address); + oop* oop_addr = NULL; + Metadata** metadata_addr = NULL; + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation *r = iter.oop_reloc(); + if (oop_addr == NULL) { + oop_addr = r->oop_addr(); + *oop_addr = (oop)data; + } else { + assert(oop_addr == r->oop_addr(), "must be only one set-oop here") ; + } + } + if (iter.type() == relocInfo::metadata_type) { + metadata_Relocation *r = iter.metadata_reloc(); + if (metadata_addr == NULL) { + metadata_addr = r->metadata_addr(); + *metadata_addr = (Metadata*)data; + } else { + assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here"); + } + } + } + } +} + +void NativeMovConstReg::set_narrow_oop(narrowOop data, CodeBlob *code /* = NULL */) { + address addr = addr_at(0); + CodeBlob* cb = (code) ? code : CodeCache::find_blob(instruction_address()); + const int invalidated_range = + MacroAssembler::patch_set_narrow_oop(addr, cb->content_begin(), (long)data); + const address start = invalidated_range < 0 ? addr + invalidated_range : addr; + // FIXME: + const int range = invalidated_range < 0 ? 4 - invalidated_range : 8; + ICache::invalidate_range(start, range); +} + +// Do not use an assertion here. Let clients decide whether they only +// want this when assertions are enabled. +#ifdef ASSERT +void NativeMovConstReg::verify() { + address addr = addr_at(0); + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); // find_nmethod() asserts if nmethod is zombie. + if (! MacroAssembler::is_load_const_at(addr) && + ! MacroAssembler::is_load_const_from_method_toc_at(addr) && + ! (cb != NULL && MacroAssembler::is_calculate_address_from_global_toc_at(addr, cb->content_begin())) && + ! (cb != NULL && MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) && + ! MacroAssembler::is_bl(*((int*) addr))) { + tty->print_cr("not a NativeMovConstReg at " PTR_FORMAT, addr); + // TODO: PPC port Disassembler::decode(addr, 20, 20, tty); + fatal(err_msg("not a NativeMovConstReg at " PTR_FORMAT, addr)); + } +} +#endif // ASSERT + +void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { + ResourceMark rm; + int code_size = 1 * BytesPerInstWord; + CodeBuffer cb(verified_entry, code_size + 1); + MacroAssembler* a = new MacroAssembler(&cb); +#ifdef COMPILER2 + assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); +#endif + // Patch this nmethod atomically. Always use illtrap/trap in debug build. + if (DEBUG_ONLY(false &&) a->is_within_range_of_b(dest, a->pc())) { + a->b(dest); + } else { + // The signal handler will continue at dest=OptoRuntime::handle_wrong_method_stub(). + if (TrapBasedNotEntrantChecks) { + // We use a special trap for marking a method as not_entrant or zombie. + a->trap_zombie_not_entrant(); + } else { + // We use an illtrap for marking a method as not_entrant or zombie. + a->illtrap(); + } + } + ICache::invalidate_range(verified_entry, code_size); +} + +#ifdef ASSERT +void NativeJump::verify() { + address addr = addr_at(0); + + NativeInstruction::verify(); + if (!NativeJump::is_jump_at(addr)) { + tty->print_cr("not a NativeJump at " PTR_FORMAT, addr); + // TODO: PPC port: Disassembler::decode(addr, 20, 20, tty); + fatal(err_msg("not a NativeJump at " PTR_FORMAT, addr)); + } +} +#endif // ASSERT + +//------------------------------------------------------------------- + +// Call trampoline stubs. +// +// Layout and instructions of a call trampoline stub: +// 0: load the TOC (part 1) +// 4: load the TOC (part 2) +// 8: load the call target from the constant pool (part 1) +// [12: load the call target from the constant pool (part 2, optional)] +// ..: branch via CTR +// + +address NativeCallTrampolineStub::encoded_destination_addr() const { + address instruction_addr = addr_at(2 * BytesPerInstWord); + assert(MacroAssembler::is_ld_largeoffset(instruction_addr), + "must be a ld with large offset (from the constant pool)"); + + return instruction_addr; +} + +address NativeCallTrampolineStub::destination() const { + CodeBlob* cb = CodeCache::find_blob(addr_at(0)); + address ctable = cb->content_begin(); + + return *(address*)(ctable + destination_toc_offset()); +} + +int NativeCallTrampolineStub::destination_toc_offset() const { + return MacroAssembler::get_ld_largeoffset_offset(encoded_destination_addr()); +} + +void NativeCallTrampolineStub::set_destination(address new_destination) { + CodeBlob* cb = CodeCache::find_blob(addr_at(0)); + address ctable = cb->content_begin(); + + *(address*)(ctable + destination_toc_offset()) = new_destination; +} + diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp new file mode 100644 index 00000000000..b70a859bf30 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_NATIVEINST_PPC_HPP +#define CPU_PPC_VM_NATIVEINST_PPC_HPP + +#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" +#include "memory/allocation.hpp" +#include "runtime/icache.hpp" +#include "runtime/os.hpp" +#include "utilities/top.hpp" + +// We have interfaces for the following instructions: +// +// - NativeInstruction +// - NativeCall +// - NativeFarCall +// - NativeMovConstReg +// - NativeJump +// - NativeIllegalInstruction +// - NativeConditionalFarBranch +// - NativeCallTrampolineStub + +// The base class for different kinds of native instruction abstractions. +// It provides the primitive operations to manipulate code relative to this. +class NativeInstruction VALUE_OBJ_CLASS_SPEC { + friend class Relocation; + + public: + bool is_sigtrap_ic_miss_check() { + assert(UseSIGTRAP, "precondition"); + return MacroAssembler::is_trap_ic_miss_check(long_at(0)); + } + + bool is_sigtrap_null_check() { + assert(UseSIGTRAP && TrapBasedNullChecks, "precondition"); + return MacroAssembler::is_trap_null_check(long_at(0)); + } + + // We use a special trap for marking a method as not_entrant or zombie + // iff UseSIGTRAP. + bool is_sigtrap_zombie_not_entrant() { + assert(UseSIGTRAP, "precondition"); + return MacroAssembler::is_trap_zombie_not_entrant(long_at(0)); + } + + // We use an illtrap for marking a method as not_entrant or zombie + // iff !UseSIGTRAP. + bool is_sigill_zombie_not_entrant() { + assert(!UseSIGTRAP, "precondition"); + // Work around a C++ compiler bug which changes 'this'. + return NativeInstruction::is_sigill_zombie_not_entrant_at(addr_at(0)); + } + static bool is_sigill_zombie_not_entrant_at(address addr); + + // SIGTRAP-based implicit range checks + bool is_sigtrap_range_check() { + assert(UseSIGTRAP && TrapBasedRangeChecks, "precondition"); + return MacroAssembler::is_trap_range_check(long_at(0)); + } + + // 'should not reach here'. + bool is_sigtrap_should_not_reach_here() { + return MacroAssembler::is_trap_should_not_reach_here(long_at(0)); + } + + bool is_safepoint_poll() { + // Is the current instruction a POTENTIAL read access to the polling page? + // The current arguments of the instruction are not checked! + return MacroAssembler::is_load_from_polling_page(long_at(0), NULL); + } + + bool is_memory_serialization(JavaThread *thread, void *ucontext) { + // Is the current instruction a write access of thread to the + // memory serialization page? + return MacroAssembler::is_memory_serialization(long_at(0), thread, ucontext); + } + + address get_stack_bang_address(void *ucontext) { + // If long_at(0) is not a stack bang, return 0. Otherwise, return + // banged address. + return MacroAssembler::get_stack_bang_address(long_at(0), ucontext); + } + + protected: + address addr_at(int offset) const { return address(this) + offset; } + int long_at(int offset) const { return *(int*)addr_at(offset); } + + public: + void verify() NOT_DEBUG_RETURN; +}; + +inline NativeInstruction* nativeInstruction_at(address address) { + NativeInstruction* inst = (NativeInstruction*)address; + inst->verify(); + return inst; +} + +// The NativeCall is an abstraction for accessing/manipulating call +// instructions. It is used to manipulate inline caches, primitive & +// dll calls, etc. +// +// Sparc distinguishes `NativeCall' and `NativeFarCall'. On PPC64, +// at present, we provide a single class `NativeCall' representing the +// sequence `load_const, mtctr, bctrl' or the sequence 'ld_from_toc, +// mtctr, bctrl'. +class NativeCall: public NativeInstruction { + public: + + enum specific_constants { + load_const_instruction_size = 28, + load_const_from_method_toc_instruction_size = 16, + instruction_size = 16 // Used in shared code for calls with reloc_info. + }; + + static bool is_call_at(address a) { + return Assembler::is_bl(*(int*)(a)); + } + + static bool is_call_before(address return_address) { + return NativeCall::is_call_at(return_address - 4); + } + + address instruction_address() const { + return addr_at(0); + } + + address next_instruction_address() const { + // We have only bl. + assert(MacroAssembler::is_bl(*(int*)instruction_address()), "Should be bl instruction!"); + return addr_at(4); + } + + address return_address() const { + return next_instruction_address(); + } + + address destination() const; + + // The parameter assert_lock disables the assertion during code generation. + void set_destination_mt_safe(address dest, bool assert_lock = true); + + address get_trampoline(); + + void verify_alignment() {} // do nothing on ppc + void verify() NOT_DEBUG_RETURN; +}; + +inline NativeCall* nativeCall_at(address instr) { + NativeCall* call = (NativeCall*)instr; + call->verify(); + return call; +} + +inline NativeCall* nativeCall_before(address return_address) { + NativeCall* call = NULL; + if (MacroAssembler::is_bl(*(int*)(return_address - 4))) + call = (NativeCall*)(return_address - 4); + call->verify(); + return call; +} + +// The NativeFarCall is an abstraction for accessing/manipulating native +// call-anywhere instructions. +// Used to call native methods which may be loaded anywhere in the address +// space, possibly out of reach of a call instruction. +class NativeFarCall: public NativeInstruction { + public: + // We use MacroAssembler::bl64_patchable() for implementing a + // call-anywhere instruction. + + // Checks whether instr points at a NativeFarCall instruction. + static bool is_far_call_at(address instr) { + return MacroAssembler::is_bl64_patchable_at(instr); + } + + // Does the NativeFarCall implementation use a pc-relative encoding + // of the call destination? + // Used when relocating code. + bool is_pcrelative() { + assert(MacroAssembler::is_bl64_patchable_at((address)this), + "unexpected call type"); + return MacroAssembler::is_bl64_patchable_pcrelative_at((address)this); + } + + // Returns the NativeFarCall's destination. + address destination() const { + assert(MacroAssembler::is_bl64_patchable_at((address)this), + "unexpected call type"); + return MacroAssembler::get_dest_of_bl64_patchable_at((address)this); + } + + // Sets the NativeCall's destination, not necessarily mt-safe. + // Used when relocating code. + void set_destination(address dest) { + // Set new destination (implementation of call may change here). + assert(MacroAssembler::is_bl64_patchable_at((address)this), + "unexpected call type"); + MacroAssembler::set_dest_of_bl64_patchable_at((address)this, dest); + } + + void verify() NOT_DEBUG_RETURN; +}; + +// Instantiates a NativeFarCall object starting at the given instruction +// address and returns the NativeFarCall object. +inline NativeFarCall* nativeFarCall_at(address instr) { + NativeFarCall* call = (NativeFarCall*)instr; + call->verify(); + return call; +} + +// An interface for accessing/manipulating native set_oop imm, reg instructions. +// (used to manipulate inlined data references, etc.) +class NativeMovConstReg: public NativeInstruction { + public: + + enum specific_constants { + load_const_instruction_size = 20, + load_const_from_method_toc_instruction_size = 8, + instruction_size = 8 // Used in shared code for calls with reloc_info. + }; + + address instruction_address() const { + return addr_at(0); + } + + address next_instruction_address() const; + + // (The [set_]data accessor respects oop_type relocs also.) + intptr_t data() const; + + // Patch the code stream. + address set_data_plain(intptr_t x, CodeBlob *code); + // Patch the code stream and oop pool. + void set_data(intptr_t x); + + // Patch narrow oop constants. Use this also for narrow klass. + void set_narrow_oop(narrowOop data, CodeBlob *code = NULL); + + void verify() NOT_DEBUG_RETURN; +}; + +inline NativeMovConstReg* nativeMovConstReg_at(address address) { + NativeMovConstReg* test = (NativeMovConstReg*)address; + test->verify(); + return test; +} + +// The NativeJump is an abstraction for accessing/manipulating native +// jump-anywhere instructions. +class NativeJump: public NativeInstruction { + public: + // We use MacroAssembler::b64_patchable() for implementing a + // jump-anywhere instruction. + + enum specific_constants { + instruction_size = MacroAssembler::b64_patchable_size + }; + + // Checks whether instr points at a NativeJump instruction. + static bool is_jump_at(address instr) { + return MacroAssembler::is_b64_patchable_at(instr) + || ( MacroAssembler::is_load_const_from_method_toc_at(instr) + && Assembler::is_mtctr(*(int*)(instr + 2 * 4)) + && Assembler::is_bctr(*(int*)(instr + 3 * 4))); + } + + // Does the NativeJump implementation use a pc-relative encoding + // of the call destination? + // Used when relocating code or patching jumps. + bool is_pcrelative() { + return MacroAssembler::is_b64_patchable_pcrelative_at((address)this); + } + + // Returns the NativeJump's destination. + address jump_destination() const { + if (MacroAssembler::is_b64_patchable_at((address)this)) { + return MacroAssembler::get_dest_of_b64_patchable_at((address)this); + } else if (MacroAssembler::is_load_const_from_method_toc_at((address)this) + && Assembler::is_mtctr(*(int*)((address)this + 2 * 4)) + && Assembler::is_bctr(*(int*)((address)this + 3 * 4))) { + return (address)((NativeMovConstReg *)this)->data(); + } else { + ShouldNotReachHere(); + return NULL; + } + } + + // Sets the NativeJump's destination, not necessarily mt-safe. + // Used when relocating code or patching jumps. + void set_jump_destination(address dest) { + // Set new destination (implementation of call may change here). + if (MacroAssembler::is_b64_patchable_at((address)this)) { + MacroAssembler::set_dest_of_b64_patchable_at((address)this, dest); + } else if (MacroAssembler::is_load_const_from_method_toc_at((address)this) + && Assembler::is_mtctr(*(int*)((address)this + 2 * 4)) + && Assembler::is_bctr(*(int*)((address)this + 3 * 4))) { + ((NativeMovConstReg *)this)->set_data((intptr_t)dest); + } else { + ShouldNotReachHere(); + } + } + + // MT-safe insertion of native jump at verified method entry + static void patch_verified_entry(address entry, address verified_entry, address dest); + + void verify() NOT_DEBUG_RETURN; + + static void check_verified_entry_alignment(address entry, address verified_entry) { + // We just patch one instruction on ppc64, so the jump doesn't have to + // be aligned. Nothing to do here. + } +}; + +// Instantiates a NativeJump object starting at the given instruction +// address and returns the NativeJump object. +inline NativeJump* nativeJump_at(address instr) { + NativeJump* call = (NativeJump*)instr; + call->verify(); + return call; +} + +// NativeConditionalFarBranch is abstraction for accessing/manipulating +// conditional far branches. +class NativeConditionalFarBranch : public NativeInstruction { + public: + + static bool is_conditional_far_branch_at(address instr) { + return MacroAssembler::is_bc_far_at(instr); + } + + address branch_destination() const { + return MacroAssembler::get_dest_of_bc_far_at((address)this); + } + + void set_branch_destination(address dest) { + MacroAssembler::set_dest_of_bc_far_at((address)this, dest); + } +}; + +inline NativeConditionalFarBranch* NativeConditionalFarBranch_at(address address) { + assert(NativeConditionalFarBranch::is_conditional_far_branch_at(address), + "must be a conditional far branch"); + return (NativeConditionalFarBranch*)address; +} + +// Call trampoline stubs. +class NativeCallTrampolineStub : public NativeInstruction { + private: + + address encoded_destination_addr() const; + + public: + + address destination() const; + int destination_toc_offset() const; + + void set_destination(address new_destination); +}; + + +inline bool is_NativeCallTrampolineStub_at(address address) { + int first_instr = *(int*)address; + return Assembler::is_addis(first_instr) && + (Register)(intptr_t)Assembler::inv_rt_field(first_instr) == R12_scratch2; +} + +inline NativeCallTrampolineStub* NativeCallTrampolineStub_at(address address) { + assert(is_NativeCallTrampolineStub_at(address), "no call trampoline found"); + return (NativeCallTrampolineStub*)address; +} + +#endif // CPU_PPC_VM_NATIVEINST_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/registerMap_ppc.hpp b/hotspot/src/cpu/ppc/vm/registerMap_ppc.hpp new file mode 100644 index 00000000000..b3d89c2ba09 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/registerMap_ppc.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_REGISTERMAP_PPC_HPP +#define CPU_PPC_VM_REGISTERMAP_PPC_HPP + +// machine-dependent implemention for register maps + friend class frame; + + private: + // This is the hook for finding a register in an "well-known" location, + // such as a register block of a predetermined format. + // Since there is none, we just return NULL. + // See registerMap_sparc.hpp for an example of grabbing registers + // from register save areas of a standard layout. + address pd_location(VMReg reg) const { return NULL; } + + // no PD state to clear or copy: + void pd_clear() {} + void pd_initialize() {} + void pd_initialize_from(const RegisterMap* map) {} + +#endif // CPU_PPC_VM_REGISTERMAP_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp b/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp new file mode 100644 index 00000000000..d5d41811dfb --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// make sure the defines don't screw up the declarations later on in this file +#define DONT_USE_REGISTER_DEFINES + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/register.hpp" +#include "register_ppc.hpp" +#ifdef TARGET_ARCH_MODEL_32 +# include "interp_masm_32.hpp" +#endif +#ifdef TARGET_ARCH_MODEL_ppc_64 +# include "interp_masm_ppc_64.hpp" +#endif + +REGISTER_DEFINITION(Register, noreg); + +REGISTER_DEFINITION(FloatRegister, fnoreg); diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.cpp b/hotspot/src/cpu/ppc/vm/register_ppc.cpp new file mode 100644 index 00000000000..5054be245c5 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/register_ppc.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "register_ppc.hpp" + +const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * 2; +const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::max_gpr + + FloatRegisterImpl::number_of_registers * 2; +const int ConcreteRegisterImpl::max_cnd = ConcreteRegisterImpl::max_fpr + + ConditionRegisterImpl::number_of_registers; + +const char* RegisterImpl::name() const { + const char* names[number_of_registers] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", + "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", + "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31" + }; + return is_valid() ? names[encoding()] : "noreg"; +} + +const char* ConditionRegisterImpl::name() const { + const char* names[number_of_registers] = { + "CR0", "CR1", "CR2", "CR3", "CCR4", "CCR5", "CCR6", "CCR7" + }; + return is_valid() ? names[encoding()] : "cnoreg"; +} + +const char* FloatRegisterImpl::name() const { + const char* names[number_of_registers] = { + "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", + "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", + "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", + "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31" + }; + return is_valid() ? names[encoding()] : "fnoreg"; +} + +const char* SpecialRegisterImpl::name() const { + const char* names[number_of_registers] = { + "SR_XER", "SR_LR", "SR_CTR", "SR_VRSAVE", "R1_SPEFSCR", "SR_PPR" + }; + return is_valid() ? names[encoding()] : "snoreg"; +} + +const char* VectorRegisterImpl::name() const { + const char* names[number_of_registers] = { + "VR0", "VR1", "VR2", "VR3", "VR4", "VR5", "VR6", "VR7", + "VR8", "VR9", "VR10", "VR11", "VR12", "VR13", "VR14", "VR15", + "VR16", "VR17", "VR18", "VR19", "VR20", "VR21", "VR22", "VR23", + "VR24", "VR25", "VR26", "VR27", "VR28", "VR29", "VR30", "VR31" + }; + return is_valid() ? names[encoding()] : "vnoreg"; +} diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.hpp b/hotspot/src/cpu/ppc/vm/register_ppc.hpp new file mode 100644 index 00000000000..66130f9f2c5 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/register_ppc.hpp @@ -0,0 +1,635 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_REGISTER_PPC_HPP +#define CPU_PPC_VM_REGISTER_PPC_HPP + +#include "asm/register.hpp" +#include "vm_version_ppc.hpp" + +// forward declaration +class Address; +class VMRegImpl; +typedef VMRegImpl* VMReg; + +// PPC64 registers +// +// See "64-bit PowerPC ELF ABI Supplement 1.7", IBM Corp. (2003-10-29). +// (http://math-atlas.sourceforge.net/devel/assembly/PPC-elf64abi-1.7.pdf) +// +// r0 Register used in function prologs (volatile) +// r1 Stack pointer (nonvolatile) +// r2 TOC pointer (volatile) +// r3 Parameter and return value (volatile) +// r4-r10 Function parameters (volatile) +// r11 Register used in calls by pointer and as an environment pointer for languages which require one (volatile) +// r12 Register used for exception handling and glink code (volatile) +// r13 Reserved for use as system thread ID +// r14-r31 Local variables (nonvolatile) +// +// f0 Scratch register (volatile) +// f1-f4 Floating point parameters and return value (volatile) +// f5-f13 Floating point parameters (volatile) +// f14-f31 Floating point values (nonvolatile) +// +// LR Link register for return address (volatile) +// CTR Loop counter (volatile) +// XER Fixed point exception register (volatile) +// FPSCR Floating point status and control register (volatile) +// +// CR0-CR1 Condition code fields (volatile) +// CR2-CCR4 Condition code fields (nonvolatile) +// CCR5-CCR7 Condition code fields (volatile) +// +// ---------------------------------------------- +// On processors with the VMX feature: +// v0-v1 Volatile scratch registers +// v2-v13 Volatile vector parameters registers +// v14-v19 Volatile scratch registers +// v20-v31 Non-volatile registers +// vrsave Non-volatile 32-bit register + + +// Use Register as shortcut +class RegisterImpl; +typedef RegisterImpl* Register; + +inline Register as_Register(int encoding) { + assert(encoding >= 0 && encoding < 32, "bad register encoding"); + return (Register)(intptr_t)encoding; +} + +// The implementation of integer registers for the Power architecture +class RegisterImpl: public AbstractRegisterImpl { + public: + enum { + number_of_registers = 32 + }; + + // general construction + inline friend Register as_Register(int encoding); + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return value(); } + VMReg as_VMReg(); + Register successor() const { return as_Register(encoding() + 1); } + + // testers + bool is_valid() const { return ( 0 <= (value()&0x7F) && (value()&0x7F) < number_of_registers); } + bool is_volatile() const { return ( 0 <= (value()&0x7F) && (value()&0x7F) <= 13 ); } + bool is_nonvolatile() const { return (14 <= (value()&0x7F) && (value()&0x7F) <= 31 ); } + + const char* name() const; +}; + +// The integer registers of the PPC architecture +CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1)); + +CONSTANT_REGISTER_DECLARATION(Register, R0, (0)); +CONSTANT_REGISTER_DECLARATION(Register, R1, (1)); +CONSTANT_REGISTER_DECLARATION(Register, R2, (2)); +CONSTANT_REGISTER_DECLARATION(Register, R3, (3)); +CONSTANT_REGISTER_DECLARATION(Register, R4, (4)); +CONSTANT_REGISTER_DECLARATION(Register, R5, (5)); +CONSTANT_REGISTER_DECLARATION(Register, R6, (6)); +CONSTANT_REGISTER_DECLARATION(Register, R7, (7)); +CONSTANT_REGISTER_DECLARATION(Register, R8, (8)); +CONSTANT_REGISTER_DECLARATION(Register, R9, (9)); +CONSTANT_REGISTER_DECLARATION(Register, R10, (10)); +CONSTANT_REGISTER_DECLARATION(Register, R11, (11)); +CONSTANT_REGISTER_DECLARATION(Register, R12, (12)); +CONSTANT_REGISTER_DECLARATION(Register, R13, (13)); +CONSTANT_REGISTER_DECLARATION(Register, R14, (14)); +CONSTANT_REGISTER_DECLARATION(Register, R15, (15)); +CONSTANT_REGISTER_DECLARATION(Register, R16, (16)); +CONSTANT_REGISTER_DECLARATION(Register, R17, (17)); +CONSTANT_REGISTER_DECLARATION(Register, R18, (18)); +CONSTANT_REGISTER_DECLARATION(Register, R19, (19)); +CONSTANT_REGISTER_DECLARATION(Register, R20, (20)); +CONSTANT_REGISTER_DECLARATION(Register, R21, (21)); +CONSTANT_REGISTER_DECLARATION(Register, R22, (22)); +CONSTANT_REGISTER_DECLARATION(Register, R23, (23)); +CONSTANT_REGISTER_DECLARATION(Register, R24, (24)); +CONSTANT_REGISTER_DECLARATION(Register, R25, (25)); +CONSTANT_REGISTER_DECLARATION(Register, R26, (26)); +CONSTANT_REGISTER_DECLARATION(Register, R27, (27)); +CONSTANT_REGISTER_DECLARATION(Register, R28, (28)); +CONSTANT_REGISTER_DECLARATION(Register, R29, (29)); +CONSTANT_REGISTER_DECLARATION(Register, R30, (30)); +CONSTANT_REGISTER_DECLARATION(Register, R31, (31)); + + +// +// Because Power has many registers, #define'ing values for them is +// beneficial in code size and is worth the cost of some of the +// dangers of defines. If a particular file has a problem with these +// defines then it's possible to turn them off in that file by +// defining DONT_USE_REGISTER_DEFINES. Register_definition_ppc.cpp +// does that so that it's able to provide real definitions of these +// registers for use in debuggers and such. +// + +#ifndef DONT_USE_REGISTER_DEFINES +#define noreg ((Register)(noreg_RegisterEnumValue)) + +#define R0 ((Register)(R0_RegisterEnumValue)) +#define R1 ((Register)(R1_RegisterEnumValue)) +#define R2 ((Register)(R2_RegisterEnumValue)) +#define R3 ((Register)(R3_RegisterEnumValue)) +#define R4 ((Register)(R4_RegisterEnumValue)) +#define R5 ((Register)(R5_RegisterEnumValue)) +#define R6 ((Register)(R6_RegisterEnumValue)) +#define R7 ((Register)(R7_RegisterEnumValue)) +#define R8 ((Register)(R8_RegisterEnumValue)) +#define R9 ((Register)(R9_RegisterEnumValue)) +#define R10 ((Register)(R10_RegisterEnumValue)) +#define R11 ((Register)(R11_RegisterEnumValue)) +#define R12 ((Register)(R12_RegisterEnumValue)) +#define R13 ((Register)(R13_RegisterEnumValue)) +#define R14 ((Register)(R14_RegisterEnumValue)) +#define R15 ((Register)(R15_RegisterEnumValue)) +#define R16 ((Register)(R16_RegisterEnumValue)) +#define R17 ((Register)(R17_RegisterEnumValue)) +#define R18 ((Register)(R18_RegisterEnumValue)) +#define R19 ((Register)(R19_RegisterEnumValue)) +#define R20 ((Register)(R20_RegisterEnumValue)) +#define R21 ((Register)(R21_RegisterEnumValue)) +#define R22 ((Register)(R22_RegisterEnumValue)) +#define R23 ((Register)(R23_RegisterEnumValue)) +#define R24 ((Register)(R24_RegisterEnumValue)) +#define R25 ((Register)(R25_RegisterEnumValue)) +#define R26 ((Register)(R26_RegisterEnumValue)) +#define R27 ((Register)(R27_RegisterEnumValue)) +#define R28 ((Register)(R28_RegisterEnumValue)) +#define R29 ((Register)(R29_RegisterEnumValue)) +#define R30 ((Register)(R30_RegisterEnumValue)) +#define R31 ((Register)(R31_RegisterEnumValue)) +#endif + +// Use ConditionRegister as shortcut +class ConditionRegisterImpl; +typedef ConditionRegisterImpl* ConditionRegister; + +inline ConditionRegister as_ConditionRegister(int encoding) { + assert(encoding >= 0 && encoding < 8, "bad condition register encoding"); + return (ConditionRegister)(intptr_t)encoding; +} + +// The implementation of condition register(s) for the PPC architecture +class ConditionRegisterImpl: public AbstractRegisterImpl { + public: + enum { + number_of_registers = 8 + }; + + // construction. + inline friend ConditionRegister as_ConditionRegister(int encoding); + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return value(); } + VMReg as_VMReg(); + + // testers + bool is_valid() const { return (0 <= value() && value() < number_of_registers); } + bool is_nonvolatile() const { return (2 <= (value()&0x7F) && (value()&0x7F) <= 4 ); } + + const char* name() const; +}; + +// The (parts of the) condition register(s) of the PPC architecture +// sys/ioctl.h on AIX defines CR0-CR3, so I name these CCR. +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR0, (0)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR1, (1)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR2, (2)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR3, (3)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR4, (4)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR5, (5)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR6, (6)); +CONSTANT_REGISTER_DECLARATION(ConditionRegister, CCR7, (7)); + +#ifndef DONT_USE_REGISTER_DEFINES + +#define CCR0 ((ConditionRegister)(CCR0_ConditionRegisterEnumValue)) +#define CCR1 ((ConditionRegister)(CCR1_ConditionRegisterEnumValue)) +#define CCR2 ((ConditionRegister)(CCR2_ConditionRegisterEnumValue)) +#define CCR3 ((ConditionRegister)(CCR3_ConditionRegisterEnumValue)) +#define CCR4 ((ConditionRegister)(CCR4_ConditionRegisterEnumValue)) +#define CCR5 ((ConditionRegister)(CCR5_ConditionRegisterEnumValue)) +#define CCR6 ((ConditionRegister)(CCR6_ConditionRegisterEnumValue)) +#define CCR7 ((ConditionRegister)(CCR7_ConditionRegisterEnumValue)) + +#endif // DONT_USE_REGISTER_DEFINES + + +// Use FloatRegister as shortcut +class FloatRegisterImpl; +typedef FloatRegisterImpl* FloatRegister; + +inline FloatRegister as_FloatRegister(int encoding) { + assert(encoding >= 0 && encoding < 32, "bad float register encoding"); + return (FloatRegister)(intptr_t)encoding; +} + +// The implementation of float registers for the PPC architecture +class FloatRegisterImpl: public AbstractRegisterImpl { + public: + enum { + number_of_registers = 32 + }; + + // construction + inline friend FloatRegister as_FloatRegister(int encoding); + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return value(); } + VMReg as_VMReg(); + FloatRegister successor() const { return as_FloatRegister(encoding() + 1); } + + // testers + bool is_valid() const { return (0 <= value() && value() < number_of_registers); } + + const char* name() const; +}; + +// The float registers of the PPC architecture +CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg, (-1)); + +CONSTANT_REGISTER_DECLARATION(FloatRegister, F0, ( 0)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F1, ( 1)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F2, ( 2)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F3, ( 3)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F4, ( 4)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F5, ( 5)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F6, ( 6)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F7, ( 7)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F8, ( 8)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F9, ( 9)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F10, (10)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F11, (11)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F12, (12)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F13, (13)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F14, (14)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F15, (15)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F16, (16)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F17, (17)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F18, (18)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F19, (19)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F20, (20)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F21, (21)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F22, (22)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F23, (23)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F24, (24)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F25, (25)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F26, (26)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F27, (27)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F28, (28)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F29, (29)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F30, (30)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F31, (31)); + +#ifndef DONT_USE_REGISTER_DEFINES +#define fnoreg ((FloatRegister)(fnoreg_FloatRegisterEnumValue)) +#define F0 ((FloatRegister)( F0_FloatRegisterEnumValue)) +#define F1 ((FloatRegister)( F1_FloatRegisterEnumValue)) +#define F2 ((FloatRegister)( F2_FloatRegisterEnumValue)) +#define F3 ((FloatRegister)( F3_FloatRegisterEnumValue)) +#define F4 ((FloatRegister)( F4_FloatRegisterEnumValue)) +#define F5 ((FloatRegister)( F5_FloatRegisterEnumValue)) +#define F6 ((FloatRegister)( F6_FloatRegisterEnumValue)) +#define F7 ((FloatRegister)( F7_FloatRegisterEnumValue)) +#define F8 ((FloatRegister)( F8_FloatRegisterEnumValue)) +#define F9 ((FloatRegister)( F9_FloatRegisterEnumValue)) +#define F10 ((FloatRegister)( F10_FloatRegisterEnumValue)) +#define F11 ((FloatRegister)( F11_FloatRegisterEnumValue)) +#define F12 ((FloatRegister)( F12_FloatRegisterEnumValue)) +#define F13 ((FloatRegister)( F13_FloatRegisterEnumValue)) +#define F14 ((FloatRegister)( F14_FloatRegisterEnumValue)) +#define F15 ((FloatRegister)( F15_FloatRegisterEnumValue)) +#define F16 ((FloatRegister)( F16_FloatRegisterEnumValue)) +#define F17 ((FloatRegister)( F17_FloatRegisterEnumValue)) +#define F18 ((FloatRegister)( F18_FloatRegisterEnumValue)) +#define F19 ((FloatRegister)( F19_FloatRegisterEnumValue)) +#define F20 ((FloatRegister)( F20_FloatRegisterEnumValue)) +#define F21 ((FloatRegister)( F21_FloatRegisterEnumValue)) +#define F22 ((FloatRegister)( F22_FloatRegisterEnumValue)) +#define F23 ((FloatRegister)( F23_FloatRegisterEnumValue)) +#define F24 ((FloatRegister)( F24_FloatRegisterEnumValue)) +#define F25 ((FloatRegister)( F25_FloatRegisterEnumValue)) +#define F26 ((FloatRegister)( F26_FloatRegisterEnumValue)) +#define F27 ((FloatRegister)( F27_FloatRegisterEnumValue)) +#define F28 ((FloatRegister)( F28_FloatRegisterEnumValue)) +#define F29 ((FloatRegister)( F29_FloatRegisterEnumValue)) +#define F30 ((FloatRegister)( F30_FloatRegisterEnumValue)) +#define F31 ((FloatRegister)( F31_FloatRegisterEnumValue)) +#endif // DONT_USE_REGISTER_DEFINES + +// Use SpecialRegister as shortcut +class SpecialRegisterImpl; +typedef SpecialRegisterImpl* SpecialRegister; + +inline SpecialRegister as_SpecialRegister(int encoding) { + return (SpecialRegister)(intptr_t)encoding; +} + +// The implementation of special registers for the Power architecture (LR, CTR and friends) +class SpecialRegisterImpl: public AbstractRegisterImpl { + public: + enum { + number_of_registers = 6 + }; + + // construction + inline friend SpecialRegister as_SpecialRegister(int encoding); + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return value(); } + VMReg as_VMReg(); + + // testers + bool is_valid() const { return 0 <= value() && value() < number_of_registers; } + + const char* name() const; +}; + +// The special registers of the PPC architecture +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_XER, (0)); +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_LR, (1)); +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_CTR, (2)); +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_VRSAVE, (3)); +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_SPEFSCR, (4)); +CONSTANT_REGISTER_DECLARATION(SpecialRegister, SR_PPR, (5)); + +#ifndef DONT_USE_REGISTER_DEFINES +#define SR_XER ((SpecialRegister)(SR_XER_SpecialRegisterEnumValue)) +#define SR_LR ((SpecialRegister)(SR_LR_SpecialRegisterEnumValue)) +#define SR_CTR ((SpecialRegister)(SR_CTR_SpecialRegisterEnumValue)) +#define SR_VRSAVE ((SpecialRegister)(SR_VRSAVE_SpecialRegisterEnumValue)) +#define SR_SPEFSCR ((SpecialRegister)(SR_SPEFSCR_SpecialRegisterEnumValue)) +#define SR_PPR ((SpecialRegister)(SR_PPR_SpecialRegisterEnumValue)) +#endif // DONT_USE_REGISTER_DEFINES + + +// Use VectorRegister as shortcut +class VectorRegisterImpl; +typedef VectorRegisterImpl* VectorRegister; + +inline VectorRegister as_VectorRegister(int encoding) { + return (VectorRegister)(intptr_t)encoding; +} + +// The implementation of vector registers for the Power architecture +class VectorRegisterImpl: public AbstractRegisterImpl { + public: + enum { + number_of_registers = 32 + }; + + // construction + inline friend VectorRegister as_VectorRegister(int encoding); + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return value(); } + + // testers + bool is_valid() const { return 0 <= value() && value() < number_of_registers; } + + const char* name() const; +}; + +// The Vector registers of the Power architecture + +CONSTANT_REGISTER_DECLARATION(VectorRegister, vnoreg, (-1)); + +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR0, ( 0)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR1, ( 1)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR2, ( 2)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR3, ( 3)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR4, ( 4)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR5, ( 5)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR6, ( 6)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR7, ( 7)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR8, ( 8)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR9, ( 9)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR10, (10)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR11, (11)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR12, (12)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR13, (13)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR14, (14)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR15, (15)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR16, (16)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR17, (17)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR18, (18)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR19, (19)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR20, (20)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR21, (21)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR22, (22)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR23, (23)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR24, (24)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR25, (25)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR26, (26)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR27, (27)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR28, (28)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR29, (29)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR30, (30)); +CONSTANT_REGISTER_DECLARATION(VectorRegister, VR31, (31)); + +#ifndef DONT_USE_REGISTER_DEFINES +#define vnoreg ((VectorRegister)(vnoreg_VectorRegisterEnumValue)) +#define VR0 ((VectorRegister)( VR0_VectorRegisterEnumValue)) +#define VR1 ((VectorRegister)( VR1_VectorRegisterEnumValue)) +#define VR2 ((VectorRegister)( VR2_VectorRegisterEnumValue)) +#define VR3 ((VectorRegister)( VR3_VectorRegisterEnumValue)) +#define VR4 ((VectorRegister)( VR4_VectorRegisterEnumValue)) +#define VR5 ((VectorRegister)( VR5_VectorRegisterEnumValue)) +#define VR6 ((VectorRegister)( VR6_VectorRegisterEnumValue)) +#define VR7 ((VectorRegister)( VR7_VectorRegisterEnumValue)) +#define VR8 ((VectorRegister)( VR8_VectorRegisterEnumValue)) +#define VR9 ((VectorRegister)( VR9_VectorRegisterEnumValue)) +#define VR10 ((VectorRegister)( VR10_VectorRegisterEnumValue)) +#define VR11 ((VectorRegister)( VR11_VectorRegisterEnumValue)) +#define VR12 ((VectorRegister)( VR12_VectorRegisterEnumValue)) +#define VR13 ((VectorRegister)( VR13_VectorRegisterEnumValue)) +#define VR14 ((VectorRegister)( VR14_VectorRegisterEnumValue)) +#define VR15 ((VectorRegister)( VR15_VectorRegisterEnumValue)) +#define VR16 ((VectorRegister)( VR16_VectorRegisterEnumValue)) +#define VR17 ((VectorRegister)( VR17_VectorRegisterEnumValue)) +#define VR18 ((VectorRegister)( VR18_VectorRegisterEnumValue)) +#define VR19 ((VectorRegister)( VR19_VectorRegisterEnumValue)) +#define VR20 ((VectorRegister)( VR20_VectorRegisterEnumValue)) +#define VR21 ((VectorRegister)( VR21_VectorRegisterEnumValue)) +#define VR22 ((VectorRegister)( VR22_VectorRegisterEnumValue)) +#define VR23 ((VectorRegister)( VR23_VectorRegisterEnumValue)) +#define VR24 ((VectorRegister)( VR24_VectorRegisterEnumValue)) +#define VR25 ((VectorRegister)( VR25_VectorRegisterEnumValue)) +#define VR26 ((VectorRegister)( VR26_VectorRegisterEnumValue)) +#define VR27 ((VectorRegister)( VR27_VectorRegisterEnumValue)) +#define VR28 ((VectorRegister)( VR28_VectorRegisterEnumValue)) +#define VR29 ((VectorRegister)( VR29_VectorRegisterEnumValue)) +#define VR30 ((VectorRegister)( VR30_VectorRegisterEnumValue)) +#define VR31 ((VectorRegister)( VR31_VectorRegisterEnumValue)) +#endif // DONT_USE_REGISTER_DEFINES + + +// Maximum number of incoming arguments that can be passed in i registers. +const int PPC_ARGS_IN_REGS_NUM = 8; + + +// Need to know the total number of registers of all sorts for SharedInfo. +// Define a class that exports it. +class ConcreteRegisterImpl : public AbstractRegisterImpl { + public: + enum { + // This number must be large enough to cover REG_COUNT (defined by c2) registers. + // There is no requirement that any ordering here matches any ordering c2 gives + // it's optoregs. + number_of_registers = + ( RegisterImpl::number_of_registers + + FloatRegisterImpl::number_of_registers ) + * 2 // register halves + + ConditionRegisterImpl::number_of_registers // condition code registers + + SpecialRegisterImpl::number_of_registers // special registers + + VectorRegisterImpl::number_of_registers // vector registers + }; + + static const int max_gpr; + static const int max_fpr; + static const int max_cnd; +}; + +// Common register declarations used in assembler code. +REGISTER_DECLARATION(Register, R0_SCRATCH, R0); // volatile +REGISTER_DECLARATION(Register, R1_SP, R1); // non-volatile +REGISTER_DECLARATION(Register, R2_TOC, R2); // volatile +REGISTER_DECLARATION(Register, R3_RET, R3); // volatile +REGISTER_DECLARATION(Register, R3_ARG1, R3); // volatile +REGISTER_DECLARATION(Register, R4_ARG2, R4); // volatile +REGISTER_DECLARATION(Register, R5_ARG3, R5); // volatile +REGISTER_DECLARATION(Register, R6_ARG4, R6); // volatile +REGISTER_DECLARATION(Register, R7_ARG5, R7); // volatile +REGISTER_DECLARATION(Register, R8_ARG6, R8); // volatile +REGISTER_DECLARATION(Register, R9_ARG7, R9); // volatile +REGISTER_DECLARATION(Register, R10_ARG8, R10); // volatile +REGISTER_DECLARATION(FloatRegister, FO_SCRATCH, F0); // volatile +REGISTER_DECLARATION(FloatRegister, F1_RET, F1); // volatile +REGISTER_DECLARATION(FloatRegister, F1_ARG1, F1); // volatile +REGISTER_DECLARATION(FloatRegister, F2_ARG2, F2); // volatile +REGISTER_DECLARATION(FloatRegister, F3_ARG3, F3); // volatile +REGISTER_DECLARATION(FloatRegister, F4_ARG4, F4); // volatile +REGISTER_DECLARATION(FloatRegister, F5_ARG5, F5); // volatile +REGISTER_DECLARATION(FloatRegister, F6_ARG6, F6); // volatile +REGISTER_DECLARATION(FloatRegister, F7_ARG7, F7); // volatile +REGISTER_DECLARATION(FloatRegister, F8_ARG8, F8); // volatile +REGISTER_DECLARATION(FloatRegister, F9_ARG9, F9); // volatile +REGISTER_DECLARATION(FloatRegister, F10_ARG10, F10); // volatile +REGISTER_DECLARATION(FloatRegister, F11_ARG11, F11); // volatile +REGISTER_DECLARATION(FloatRegister, F12_ARG12, F12); // volatile +REGISTER_DECLARATION(FloatRegister, F13_ARG13, F13); // volatile + +#ifndef DONT_USE_REGISTER_DEFINES +#define R0_SCRATCH AS_REGISTER(Register, R0) +#define R1_SP AS_REGISTER(Register, R1) +#define R2_TOC AS_REGISTER(Register, R2) +#define R3_RET AS_REGISTER(Register, R3) +#define R3_ARG1 AS_REGISTER(Register, R3) +#define R4_ARG2 AS_REGISTER(Register, R4) +#define R5_ARG3 AS_REGISTER(Register, R5) +#define R6_ARG4 AS_REGISTER(Register, R6) +#define R7_ARG5 AS_REGISTER(Register, R7) +#define R8_ARG6 AS_REGISTER(Register, R8) +#define R9_ARG7 AS_REGISTER(Register, R9) +#define R10_ARG8 AS_REGISTER(Register, R10) +#define FO_SCRATCH AS_REGISTER(FloatRegister, F0) +#define F1_RET AS_REGISTER(FloatRegister, F1) +#define F1_ARG1 AS_REGISTER(FloatRegister, F1) +#define F2_ARG2 AS_REGISTER(FloatRegister, F2) +#define F3_ARG3 AS_REGISTER(FloatRegister, F3) +#define F4_ARG4 AS_REGISTER(FloatRegister, F4) +#define F5_ARG5 AS_REGISTER(FloatRegister, F5) +#define F6_ARG6 AS_REGISTER(FloatRegister, F6) +#define F7_ARG7 AS_REGISTER(FloatRegister, F7) +#define F8_ARG8 AS_REGISTER(FloatRegister, F8) +#define F9_ARG9 AS_REGISTER(FloatRegister, F9) +#define F10_ARG10 AS_REGISTER(FloatRegister, F10) +#define F11_ARG11 AS_REGISTER(FloatRegister, F11) +#define F12_ARG12 AS_REGISTER(FloatRegister, F12) +#define F13_ARG13 AS_REGISTER(FloatRegister, F13) +#endif + +// Register declarations to be used in frame manager assembly code. +// Use only non-volatile registers in order to keep values across C-calls. +REGISTER_DECLARATION(Register, R14_state, R14); // address of new cInterpreter. +REGISTER_DECLARATION(Register, R15_prev_state, R15); // address of old cInterpreter +REGISTER_DECLARATION(Register, R16_thread, R16); // address of current thread +REGISTER_DECLARATION(Register, R17_tos, R17); // address of Java tos (prepushed). +REGISTER_DECLARATION(Register, R18_locals, R18); // address of first param slot (receiver). +REGISTER_DECLARATION(Register, R19_method, R19); // address of current method +#ifndef DONT_USE_REGISTER_DEFINES +#define R14_state AS_REGISTER(Register, R14) +#define R15_prev_state AS_REGISTER(Register, R15) +#define R16_thread AS_REGISTER(Register, R16) +#define R17_tos AS_REGISTER(Register, R17) +#define R18_locals AS_REGISTER(Register, R18) +#define R19_method AS_REGISTER(Register, R19) +#define R21_sender_SP AS_REGISTER(Register, R21) +#define R23_method_handle AS_REGISTER(Register, R23) +#endif + +// Temporary registers to be used within frame manager. We can use +// the non-volatiles because the call stub has saved them. +// Use only non-volatile registers in order to keep values across C-calls. +REGISTER_DECLARATION(Register, R21_tmp1, R21); +REGISTER_DECLARATION(Register, R22_tmp2, R22); +REGISTER_DECLARATION(Register, R23_tmp3, R23); +REGISTER_DECLARATION(Register, R24_tmp4, R24); +REGISTER_DECLARATION(Register, R25_tmp5, R25); +REGISTER_DECLARATION(Register, R26_tmp6, R26); +REGISTER_DECLARATION(Register, R27_tmp7, R27); +REGISTER_DECLARATION(Register, R28_tmp8, R28); +REGISTER_DECLARATION(Register, R29_tmp9, R29); +REGISTER_DECLARATION(Register, R30_polling_page, R30); +#ifndef DONT_USE_REGISTER_DEFINES +#define R21_tmp1 AS_REGISTER(Register, R21) +#define R22_tmp2 AS_REGISTER(Register, R22) +#define R23_tmp3 AS_REGISTER(Register, R23) +#define R24_tmp4 AS_REGISTER(Register, R24) +#define R25_tmp5 AS_REGISTER(Register, R25) +#define R26_tmp6 AS_REGISTER(Register, R26) +#define R27_tmp7 AS_REGISTER(Register, R27) +#define R28_tmp8 AS_REGISTER(Register, R28) +#define R29_tmp9 AS_REGISTER(Register, R29) +#define R30_polling_page AS_REGISTER(Register, R30) + +#define CCR4_is_synced AS_REGISTER(ConditionRegister, CCR4) +#endif + +// Scratch registers are volatile. +REGISTER_DECLARATION(Register, R11_scratch1, R11); +REGISTER_DECLARATION(Register, R12_scratch2, R12); +#ifndef DONT_USE_REGISTER_DEFINES +#define R11_scratch1 AS_REGISTER(Register, R11) +#define R12_scratch2 AS_REGISTER(Register, R12) +#endif + +#endif // CPU_PPC_VM_REGISTER_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp new file mode 100644 index 00000000000..b7c17981705 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.inline.hpp" +#include "assembler_ppc.inline.hpp" +#include "code/relocInfo.hpp" +#include "nativeInst_ppc.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/safepoint.hpp" + +void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { + bool copy_back_to_oop_pool = true; // TODO: PPC port + // The following comment is from the declaration of DataRelocation: + // + // "The "o" (displacement) argument is relevant only to split relocations + // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns + // can encode more than 32 bits between them. This allows compilers to + // share set-hi instructions between addresses that differ by a small + // offset (e.g., different static variables in the same class). + // On such machines, the "x" argument to set_value on all set-lo + // instructions must be the same as the "x" argument for the + // corresponding set-hi instructions. The "o" arguments for the + // set-hi instructions are ignored, and must not affect the high-half + // immediate constant. The "o" arguments for the set-lo instructions are + // added into the low-half immediate constant, and must not overflow it." + // + // Currently we don't support splitting of relocations, so o must be + // zero: + assert(o == 0, "tried to split relocations"); + + if (!verify_only) { + if (format() != 1) { + nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code()); + } else { + assert(type() == relocInfo::oop_type || type() == relocInfo::metadata_type, + "how to encode else?"); + narrowOop no = (type() == relocInfo::oop_type) ? + oopDesc::encode_heap_oop((oop)x) : oopDesc::encode_klass((Klass*)x); + nativeMovConstReg_at(addr())->set_narrow_oop(no, code()); + } + } else { + assert((address) (nativeMovConstReg_at(addr())->data()) == x, "data must match"); + } +} + +address Relocation::pd_call_destination(address orig_addr) { + intptr_t adj = 0; + address inst_loc = addr(); + + if (orig_addr != NULL) { + // We just moved this call instruction from orig_addr to addr(). + // This means its target will appear to have grown by addr() - orig_addr. + adj = -(inst_loc - orig_addr); + } + if (NativeFarCall::is_far_call_at(inst_loc)) { + NativeFarCall* call = nativeFarCall_at(inst_loc); + return call->destination() + (intptr_t)(call->is_pcrelative() ? adj : 0); + } else if (NativeJump::is_jump_at(inst_loc)) { + NativeJump* jump = nativeJump_at(inst_loc); + return jump->jump_destination() + (intptr_t)(jump->is_pcrelative() ? adj : 0); + } else if (NativeConditionalFarBranch::is_conditional_far_branch_at(inst_loc)) { + NativeConditionalFarBranch* branch = NativeConditionalFarBranch_at(inst_loc); + return branch->branch_destination(); + } else { + // There are two instructions at the beginning of a stub, therefore we + // load at orig_addr + 8. + orig_addr = nativeCall_at(inst_loc)->get_trampoline(); + if (orig_addr == NULL) { + return (address) -1; + } else { + return (address) nativeMovConstReg_at(orig_addr + 8)->data(); + } + } +} + +void Relocation::pd_set_call_destination(address x) { + address inst_loc = addr(); + + if (NativeFarCall::is_far_call_at(inst_loc)) { + NativeFarCall* call = nativeFarCall_at(inst_loc); + call->set_destination(x); + } else if (NativeJump::is_jump_at(inst_loc)) { + NativeJump* jump= nativeJump_at(inst_loc); + jump->set_jump_destination(x); + } else if (NativeConditionalFarBranch::is_conditional_far_branch_at(inst_loc)) { + NativeConditionalFarBranch* branch = NativeConditionalFarBranch_at(inst_loc); + branch->set_branch_destination(x); + } else { + NativeCall* call = nativeCall_at(inst_loc); + call->set_destination_mt_safe(x, false); + } +} + +address* Relocation::pd_address_in_code() { + ShouldNotReachHere(); + return 0; +} + +address Relocation::pd_get_address_from_code() { + return (address)(nativeMovConstReg_at(addr())->data()); +} + +void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { +} + +void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { +} + +void metadata_Relocation::pd_fix_value(address x) { +} diff --git a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.hpp b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.hpp new file mode 100644 index 00000000000..3cd7da47ec8 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_RELOCINFO_PPC_HPP +#define CPU_PPC_VM_RELOCINFO_PPC_HPP + + // machine-dependent parts of class relocInfo + private: + enum { + // Since Power instructions are whole words, + // the two low-order offset bits can always be discarded. + offset_unit = 4, + + // There is no need for format bits; the instructions are + // sufficiently self-identifying. +#ifndef _LP64 + format_width = 0 +#else + // Except narrow oops in 64-bits VM. + format_width = 1 +#endif + }; + +#endif // CPU_PPC_VM_RELOCINFO_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp new file mode 100644 index 00000000000..444882ffd2e --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -0,0 +1,3209 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/debugInfoRec.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "oops/compiledICHolder.hpp" +#include "prims/jvmtiRedefineClassesTrace.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/vframeArray.hpp" +#include "vmreg_ppc.inline.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +#define __ masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + + +// Used by generate_deopt_blob. Defined in .ad file. +extern uint size_deopt_handler(); + + +class RegisterSaver { + // Used for saving volatile registers. + public: + + // Support different return pc locations. + enum ReturnPCLocation { + return_pc_is_lr, + return_pc_is_r4, + return_pc_is_thread_saved_exception_pc + }; + + static OopMap* push_frame_abi112_and_save_live_registers(MacroAssembler* masm, + int* out_frame_size_in_bytes, + bool generate_oop_map, + int return_pc_adjustment, + ReturnPCLocation return_pc_location); + static void restore_live_registers_and_pop_frame(MacroAssembler* masm, + int frame_size_in_bytes, + bool restore_ctr); + + static void push_frame_and_save_argument_registers(MacroAssembler* masm, + Register r_temp, + int frame_size, + int total_args, + const VMRegPair *regs, const VMRegPair *regs2 = NULL); + static void restore_argument_registers_and_pop_frame(MacroAssembler*masm, + int frame_size, + int total_args, + const VMRegPair *regs, const VMRegPair *regs2 = NULL); + + // During deoptimization only the result registers need to be restored + // all the other values have already been extracted. + static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes); + + // Constants and data structures: + + typedef enum { + int_reg = 0, + float_reg = 1, + special_reg = 2 + } RegisterType; + + typedef enum { + reg_size = 8, + half_reg_size = reg_size / 2, + } RegisterConstants; + + typedef struct { + RegisterType reg_type; + int reg_num; + VMReg vmreg; + } LiveRegType; +}; + + +#define RegisterSaver_LiveSpecialReg(regname) \ + { RegisterSaver::special_reg, regname->encoding(), regname->as_VMReg() } + +#define RegisterSaver_LiveIntReg(regname) \ + { RegisterSaver::int_reg, regname->encoding(), regname->as_VMReg() } + +#define RegisterSaver_LiveFloatReg(regname) \ + { RegisterSaver::float_reg, regname->encoding(), regname->as_VMReg() } + +static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = { + // Live registers which get spilled to the stack. Register + // positions in this array correspond directly to the stack layout. + + // + // live special registers: + // + RegisterSaver_LiveSpecialReg(SR_CTR), + // + // live float registers: + // + RegisterSaver_LiveFloatReg( F0 ), + RegisterSaver_LiveFloatReg( F1 ), + RegisterSaver_LiveFloatReg( F2 ), + RegisterSaver_LiveFloatReg( F3 ), + RegisterSaver_LiveFloatReg( F4 ), + RegisterSaver_LiveFloatReg( F5 ), + RegisterSaver_LiveFloatReg( F6 ), + RegisterSaver_LiveFloatReg( F7 ), + RegisterSaver_LiveFloatReg( F8 ), + RegisterSaver_LiveFloatReg( F9 ), + RegisterSaver_LiveFloatReg( F10 ), + RegisterSaver_LiveFloatReg( F11 ), + RegisterSaver_LiveFloatReg( F12 ), + RegisterSaver_LiveFloatReg( F13 ), + RegisterSaver_LiveFloatReg( F14 ), + RegisterSaver_LiveFloatReg( F15 ), + RegisterSaver_LiveFloatReg( F16 ), + RegisterSaver_LiveFloatReg( F17 ), + RegisterSaver_LiveFloatReg( F18 ), + RegisterSaver_LiveFloatReg( F19 ), + RegisterSaver_LiveFloatReg( F20 ), + RegisterSaver_LiveFloatReg( F21 ), + RegisterSaver_LiveFloatReg( F22 ), + RegisterSaver_LiveFloatReg( F23 ), + RegisterSaver_LiveFloatReg( F24 ), + RegisterSaver_LiveFloatReg( F25 ), + RegisterSaver_LiveFloatReg( F26 ), + RegisterSaver_LiveFloatReg( F27 ), + RegisterSaver_LiveFloatReg( F28 ), + RegisterSaver_LiveFloatReg( F29 ), + RegisterSaver_LiveFloatReg( F30 ), + RegisterSaver_LiveFloatReg( F31 ), + // + // live integer registers: + // + RegisterSaver_LiveIntReg( R0 ), + //RegisterSaver_LiveIntReg( R1 ), // stack pointer + RegisterSaver_LiveIntReg( R2 ), + RegisterSaver_LiveIntReg( R3 ), + RegisterSaver_LiveIntReg( R4 ), + RegisterSaver_LiveIntReg( R5 ), + RegisterSaver_LiveIntReg( R6 ), + RegisterSaver_LiveIntReg( R7 ), + RegisterSaver_LiveIntReg( R8 ), + RegisterSaver_LiveIntReg( R9 ), + RegisterSaver_LiveIntReg( R10 ), + RegisterSaver_LiveIntReg( R11 ), + RegisterSaver_LiveIntReg( R12 ), + //RegisterSaver_LiveIntReg( R13 ), // system thread id + RegisterSaver_LiveIntReg( R14 ), + RegisterSaver_LiveIntReg( R15 ), + RegisterSaver_LiveIntReg( R16 ), + RegisterSaver_LiveIntReg( R17 ), + RegisterSaver_LiveIntReg( R18 ), + RegisterSaver_LiveIntReg( R19 ), + RegisterSaver_LiveIntReg( R20 ), + RegisterSaver_LiveIntReg( R21 ), + RegisterSaver_LiveIntReg( R22 ), + RegisterSaver_LiveIntReg( R23 ), + RegisterSaver_LiveIntReg( R24 ), + RegisterSaver_LiveIntReg( R25 ), + RegisterSaver_LiveIntReg( R26 ), + RegisterSaver_LiveIntReg( R27 ), + RegisterSaver_LiveIntReg( R28 ), + RegisterSaver_LiveIntReg( R29 ), + RegisterSaver_LiveIntReg( R31 ), + RegisterSaver_LiveIntReg( R30 ), // r30 must be the last register +}; + +OopMap* RegisterSaver::push_frame_abi112_and_save_live_registers(MacroAssembler* masm, + int* out_frame_size_in_bytes, + bool generate_oop_map, + int return_pc_adjustment, + ReturnPCLocation return_pc_location) { + // Push an abi112-frame and store all registers which may be live. + // If requested, create an OopMap: Record volatile registers as + // callee-save values in an OopMap so their save locations will be + // propagated to the RegisterMap of the caller frame during + // StackFrameStream construction (needed for deoptimization; see + // compiledVFrame::create_stack_value). + // If return_pc_adjustment != 0 adjust the return pc by return_pc_adjustment. + + int i; + int offset; + + // calcualte frame size + const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / + sizeof(RegisterSaver::LiveRegType); + const int register_save_size = regstosave_num * reg_size; + const int frame_size_in_bytes = round_to(register_save_size, frame::alignment_in_bytes) + + frame::abi_112_size; + *out_frame_size_in_bytes = frame_size_in_bytes; + const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); + const int register_save_offset = frame_size_in_bytes - register_save_size; + + // OopMap frame size is in c2 stack slots (sizeof(jint)) not bytes or words. + OopMap* map = generate_oop_map ? new OopMap(frame_size_in_slots, 0) : NULL; + + BLOCK_COMMENT("push_frame_abi112_and_save_live_registers {"); + + // Save r30 in the last slot of the not yet pushed frame so that we + // can use it as scratch reg. + __ std(R30, -reg_size, R1_SP); + assert(-reg_size == register_save_offset - frame_size_in_bytes + ((regstosave_num-1)*reg_size), + "consistency check"); + + // save the flags + // Do the save_LR_CR by hand and adjust the return pc if requested. + __ mfcr(R30); + __ std(R30, _abi(cr), R1_SP); + switch (return_pc_location) { + case return_pc_is_lr: __ mflr(R30); break; + case return_pc_is_r4: __ mr(R30, R4); break; + case return_pc_is_thread_saved_exception_pc: + __ ld(R30, thread_(saved_exception_pc)); break; + default: ShouldNotReachHere(); + } + if (return_pc_adjustment != 0) + __ addi(R30, R30, return_pc_adjustment); + __ std(R30, _abi(lr), R1_SP); + + // push a new frame + __ push_frame(frame_size_in_bytes, R30); + + // save all registers (ints and floats) + offset = register_save_offset; + for (int i = 0; i < regstosave_num; i++) { + int reg_num = RegisterSaver_LiveRegs[i].reg_num; + int reg_type = RegisterSaver_LiveRegs[i].reg_type; + + switch (reg_type) { + case RegisterSaver::int_reg: { + if (reg_num != 30) { // We spilled R30 right at the beginning. + __ std(as_Register(reg_num), offset, R1_SP); + } + break; + } + case RegisterSaver::float_reg: { + __ stfd(as_FloatRegister(reg_num), offset, R1_SP); + break; + } + case RegisterSaver::special_reg: { + if (reg_num == SR_CTR_SpecialRegisterEnumValue) { + __ mfctr(R30); + __ std(R30, offset, R1_SP); + } else { + Unimplemented(); + } + break; + } + default: + ShouldNotReachHere(); + } + + if (generate_oop_map) { + map->set_callee_saved(VMRegImpl::stack2reg(offset>>2), + RegisterSaver_LiveRegs[i].vmreg); + map->set_callee_saved(VMRegImpl::stack2reg((offset + half_reg_size)>>2), + RegisterSaver_LiveRegs[i].vmreg->next()); + } + offset += reg_size; + } + + BLOCK_COMMENT("} push_frame_abi112_and_save_live_registers"); + + // And we're done. + return map; +} + + +// Pop the current frame and restore all the registers that we +// saved. +void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm, + int frame_size_in_bytes, + bool restore_ctr) { + int i; + int offset; + const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / + sizeof(RegisterSaver::LiveRegType); + const int register_save_size = regstosave_num * reg_size; + const int register_save_offset = frame_size_in_bytes - register_save_size; + + BLOCK_COMMENT("restore_live_registers_and_pop_frame {"); + + // restore all registers (ints and floats) + offset = register_save_offset; + for (int i = 0; i < regstosave_num; i++) { + int reg_num = RegisterSaver_LiveRegs[i].reg_num; + int reg_type = RegisterSaver_LiveRegs[i].reg_type; + + switch (reg_type) { + case RegisterSaver::int_reg: { + if (reg_num != 30) // R30 restored at the end, it's the tmp reg! + __ ld(as_Register(reg_num), offset, R1_SP); + break; + } + case RegisterSaver::float_reg: { + __ lfd(as_FloatRegister(reg_num), offset, R1_SP); + break; + } + case RegisterSaver::special_reg: { + if (reg_num == SR_CTR_SpecialRegisterEnumValue) { + if (restore_ctr) { // Nothing to do here if ctr already contains the next address. + __ ld(R30, offset, R1_SP); + __ mtctr(R30); + } + } else { + Unimplemented(); + } + break; + } + default: + ShouldNotReachHere(); + } + offset += reg_size; + } + + // pop the frame + __ pop_frame(); + + // restore the flags + __ restore_LR_CR(R30); + + // restore scratch register's value + __ ld(R30, -reg_size, R1_SP); + + BLOCK_COMMENT("} restore_live_registers_and_pop_frame"); +} + +void RegisterSaver::push_frame_and_save_argument_registers(MacroAssembler* masm, Register r_temp, + int frame_size,int total_args, const VMRegPair *regs, + const VMRegPair *regs2) { + __ push_frame(frame_size, r_temp); + int st_off = frame_size - wordSize; + for (int i = 0; i < total_args; i++) { + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_Register()) { + Register r = r_1->as_Register(); + __ std(r, st_off, R1_SP); + st_off -= wordSize; + } else if (r_1->is_FloatRegister()) { + FloatRegister f = r_1->as_FloatRegister(); + __ stfd(f, st_off, R1_SP); + st_off -= wordSize; + } + } + if (regs2 != NULL) { + for (int i = 0; i < total_args; i++) { + VMReg r_1 = regs2[i].first(); + VMReg r_2 = regs2[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_Register()) { + Register r = r_1->as_Register(); + __ std(r, st_off, R1_SP); + st_off -= wordSize; + } else if (r_1->is_FloatRegister()) { + FloatRegister f = r_1->as_FloatRegister(); + __ stfd(f, st_off, R1_SP); + st_off -= wordSize; + } + } + } +} + +void RegisterSaver::restore_argument_registers_and_pop_frame(MacroAssembler*masm, int frame_size, + int total_args, const VMRegPair *regs, + const VMRegPair *regs2) { + int st_off = frame_size - wordSize; + for (int i = 0; i < total_args; i++) { + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (r_1->is_Register()) { + Register r = r_1->as_Register(); + __ ld(r, st_off, R1_SP); + st_off -= wordSize; + } else if (r_1->is_FloatRegister()) { + FloatRegister f = r_1->as_FloatRegister(); + __ lfd(f, st_off, R1_SP); + st_off -= wordSize; + } + } + if (regs2 != NULL) + for (int i = 0; i < total_args; i++) { + VMReg r_1 = regs2[i].first(); + VMReg r_2 = regs2[i].second(); + if (r_1->is_Register()) { + Register r = r_1->as_Register(); + __ ld(r, st_off, R1_SP); + st_off -= wordSize; + } else if (r_1->is_FloatRegister()) { + FloatRegister f = r_1->as_FloatRegister(); + __ lfd(f, st_off, R1_SP); + st_off -= wordSize; + } + } + __ pop_frame(); +} + +// Restore the registers that might be holding a result. +void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes) { + int i; + int offset; + const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / + sizeof(RegisterSaver::LiveRegType); + const int register_save_size = regstosave_num * reg_size; + const int register_save_offset = frame_size_in_bytes - register_save_size; + + // restore all result registers (ints and floats) + offset = register_save_offset; + for (int i = 0; i < regstosave_num; i++) { + int reg_num = RegisterSaver_LiveRegs[i].reg_num; + int reg_type = RegisterSaver_LiveRegs[i].reg_type; + switch (reg_type) { + case RegisterSaver::int_reg: { + if (as_Register(reg_num)==R3_RET) // int result_reg + __ ld(as_Register(reg_num), offset, R1_SP); + break; + } + case RegisterSaver::float_reg: { + if (as_FloatRegister(reg_num)==F1_RET) // float result_reg + __ lfd(as_FloatRegister(reg_num), offset, R1_SP); + break; + } + case RegisterSaver::special_reg: { + // Special registers don't hold a result. + break; + } + default: + ShouldNotReachHere(); + } + offset += reg_size; + } +} + +// Is vector's size (in bytes) bigger than a size saved by default? +bool SharedRuntime::is_wide_vector(int size) { + ResourceMark rm; + // Note, MaxVectorSize == 8 on PPC64. + assert(size <= 8, err_msg_res("%d bytes vectors are not supported", size)); + return size > 8; +} +#ifdef COMPILER2 +static int reg2slot(VMReg r) { + return r->reg2stack() + SharedRuntime::out_preserve_stack_slots(); +} + +static int reg2offset(VMReg r) { + return (r->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; +} +#endif + +// --------------------------------------------------------------------------- +// Read the array of BasicTypes from a signature, and compute where the +// arguments should go. Values in the VMRegPair regs array refer to 4-byte +// quantities. Values less than VMRegImpl::stack0 are registers, those above +// refer to 4-byte stack slots. All stack slots are based off of the stack pointer +// as framesizes are fixed. +// VMRegImpl::stack0 refers to the first slot 0(sp). +// and VMRegImpl::stack0+1 refers to the memory word 4-bytes higher. Register +// up to RegisterImpl::number_of_registers) are the 64-bit +// integer registers. + +// Note: the INPUTS in sig_bt are in units of Java argument words, which are +// either 32-bit or 64-bit depending on the build. The OUTPUTS are in 32-bit +// units regardless of build. Of course for i486 there is no 64 bit build + +// The Java calling convention is a "shifted" version of the C ABI. +// By skipping the first C ABI register we can call non-static jni methods +// with small numbers of arguments without having to shuffle the arguments +// at all. Since we control the java ABI we ought to at least get some +// advantage out of it. + +const VMReg java_iarg_reg[8] = { + R3->as_VMReg(), + R4->as_VMReg(), + R5->as_VMReg(), + R6->as_VMReg(), + R7->as_VMReg(), + R8->as_VMReg(), + R9->as_VMReg(), + R10->as_VMReg() +}; + +const VMReg java_farg_reg[13] = { + F1->as_VMReg(), + F2->as_VMReg(), + F3->as_VMReg(), + F4->as_VMReg(), + F5->as_VMReg(), + F6->as_VMReg(), + F7->as_VMReg(), + F8->as_VMReg(), + F9->as_VMReg(), + F10->as_VMReg(), + F11->as_VMReg(), + F12->as_VMReg(), + F13->as_VMReg() +}; + +const int num_java_iarg_registers = sizeof(java_iarg_reg) / sizeof(java_iarg_reg[0]); +const int num_java_farg_registers = sizeof(java_farg_reg) / sizeof(java_farg_reg[0]); + +int SharedRuntime::java_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, + int total_args_passed, + int is_outgoing) { + // C2c calling conventions for compiled-compiled calls. + // Put 8 ints/longs into registers _AND_ 13 float/doubles into + // registers _AND_ put the rest on the stack. + + const int inc_stk_for_intfloat = 1; // 1 slots for ints and floats + const int inc_stk_for_longdouble = 2; // 2 slots for longs and doubles + + int i; + VMReg reg; + int stk = 0; + int ireg = 0; + int freg = 0; + + // We put the first 8 arguments into registers and the rest on the + // stack, float arguments are already in their argument registers + // due to c2c calling conventions (see calling_convention). + for (int i = 0; i < total_args_passed; ++i) { + switch(sig_bt[i]) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + if (ireg < num_java_iarg_registers) { + // Put int/ptr in register + reg = java_iarg_reg[ireg]; + ++ireg; + } else { + // Put int/ptr on stack. + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_intfloat; + } + regs[i].set1(reg); + break; + case T_LONG: + assert(sig_bt[i+1] == T_VOID, "expecting half"); + if (ireg < num_java_iarg_registers) { + // Put long in register. + reg = java_iarg_reg[ireg]; + ++ireg; + } else { + // Put long on stack. They must be aligned to 2 slots. + if (stk & 0x1) ++stk; + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_longdouble; + } + regs[i].set2(reg); + break; + case T_OBJECT: + case T_ARRAY: + case T_ADDRESS: + if (ireg < num_java_iarg_registers) { + // Put ptr in register. + reg = java_iarg_reg[ireg]; + ++ireg; + } else { + // Put ptr on stack. Objects must be aligned to 2 slots too, + // because "64-bit pointers record oop-ishness on 2 aligned + // adjacent registers." (see OopFlow::build_oop_map). + if (stk & 0x1) ++stk; + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_longdouble; + } + regs[i].set2(reg); + break; + case T_FLOAT: + if (freg < num_java_farg_registers) { + // Put float in register. + reg = java_farg_reg[freg]; + ++freg; + } else { + // Put float on stack. + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_intfloat; + } + regs[i].set1(reg); + break; + case T_DOUBLE: + assert(sig_bt[i+1] == T_VOID, "expecting half"); + if (freg < num_java_farg_registers) { + // Put double in register. + reg = java_farg_reg[freg]; + ++freg; + } else { + // Put double on stack. They must be aligned to 2 slots. + if (stk & 0x1) ++stk; + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_longdouble; + } + regs[i].set2(reg); + break; + case T_VOID: + // Do not count halves. + regs[i].set_bad(); + break; + default: + ShouldNotReachHere(); + } + } + return round_to(stk, 2); +} + +#ifdef COMPILER2 +// Calling convention for calling C code. +int SharedRuntime::c_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, + VMRegPair *regs2, + int total_args_passed) { + // Calling conventions for C runtime calls and calls to JNI native methods. + // + // PPC64 convention: Hoist the first 8 int/ptr/long's in the first 8 + // int regs, leaving int regs undefined if the arg is flt/dbl. Hoist + // the first 13 flt/dbl's in the first 13 fp regs but additionally + // copy flt/dbl to the stack if they are beyond the 8th argument. + + const VMReg iarg_reg[8] = { + R3->as_VMReg(), + R4->as_VMReg(), + R5->as_VMReg(), + R6->as_VMReg(), + R7->as_VMReg(), + R8->as_VMReg(), + R9->as_VMReg(), + R10->as_VMReg() + }; + + const VMReg farg_reg[13] = { + F1->as_VMReg(), + F2->as_VMReg(), + F3->as_VMReg(), + F4->as_VMReg(), + F5->as_VMReg(), + F6->as_VMReg(), + F7->as_VMReg(), + F8->as_VMReg(), + F9->as_VMReg(), + F10->as_VMReg(), + F11->as_VMReg(), + F12->as_VMReg(), + F13->as_VMReg() + }; + + const int num_iarg_registers = sizeof(iarg_reg) / sizeof(iarg_reg[0]); + const int num_farg_registers = sizeof(farg_reg) / sizeof(farg_reg[0]); + + // The first 8 arguments are not passed on the stack. + const int num_args_in_regs = 8; +#define put_arg_in_reg(arg) ((arg) < num_args_in_regs) + + // Check calling conventions consistency. + assert(num_iarg_registers == num_args_in_regs + && num_iarg_registers == 8 + && num_farg_registers == 13, + "consistency"); + + // `Stk' counts stack slots. Due to alignment, 32 bit values occupy + // 2 such slots, like 64 bit values do. + const int inc_stk_for_intfloat = 2; // 2 slots for ints and floats + const int inc_stk_for_longdouble = 2; // 2 slots for longs and doubles + + int ill_i = 0; + int ill_t = 0; + int i; + VMReg reg; + // Leave room for C-compatible ABI_112. + int stk = (frame::abi_112_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size; + int arg = 0; + int freg = 0; + + // Avoid passing C arguments in the wrong stack slots. + assert((SharedRuntime::out_preserve_stack_slots() + stk) * VMRegImpl::stack_slot_size == 112, + "passing C arguments in wrong stack slots"); + + // We fill-out regs AND regs2 if an argument must be passed in a + // register AND in a stack slot. If regs2 is NULL in such a + // situation, we bail-out with a fatal error. + for (int i = 0; i < total_args_passed; ++i, ++arg) { + // Initialize regs2 to BAD. + if (regs2 != NULL) regs2[i].set_bad(); + + switch(sig_bt[i]) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + // We must cast ints to longs and use full 64 bit stack slots + // here. We do the cast in GraphKit::gen_stub() and just guard + // here against loosing that change. + Unimplemented(); // TODO: PPC port + /* + assert(SharedRuntime::c_calling_convention_requires_ints_as_longs(), + "argument of type int should be promoted to type long"); + */ + guarantee(i > 0 && sig_bt[i-1] == T_LONG, + "argument of type (bt) should have been promoted to type (T_LONG,bt) for bt in " + "{T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); + // Do not count halves. + regs[i].set_bad(); + --arg; + break; + case T_LONG: + guarantee(sig_bt[i+1] == T_VOID || + sig_bt[i+1] == T_BOOLEAN || sig_bt[i+1] == T_CHAR || + sig_bt[i+1] == T_BYTE || sig_bt[i+1] == T_SHORT || + sig_bt[i+1] == T_INT, + "expecting type (T_LONG,half) or type (T_LONG,bt) with bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); + case T_OBJECT: + case T_ARRAY: + case T_ADDRESS: + case T_METADATA: + // Oops are already boxed if required (JNI). + if (put_arg_in_reg(arg)) { + reg = iarg_reg[arg]; + } else { + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_longdouble; + } + regs[i].set2(reg); + break; + case T_FLOAT: + if (put_arg_in_reg(arg)) { + reg = farg_reg[freg]; + } else { + // Put float on stack +# if defined(LINUX) + reg = VMRegImpl::stack2reg(stk+1); +# elif defined(AIX) + reg = VMRegImpl::stack2reg(stk); +# else +# error "unknown OS" +# endif + stk += inc_stk_for_intfloat; + } + + if (freg < num_farg_registers) { + // There are still some float argument registers left. Put the + // float in a register if not already done. + if (reg != farg_reg[freg]) { + guarantee(regs2 != NULL, "must pass float in register and stack slot"); + VMReg reg2 = farg_reg[freg]; + regs2[i].set1(reg2); + } + ++freg; + } + + regs[i].set1(reg); + break; + case T_DOUBLE: + assert(sig_bt[i+1] == T_VOID, "expecting half"); + if (put_arg_in_reg(arg)) { + reg = farg_reg[freg]; + } else { + // Put double on stack. + reg = VMRegImpl::stack2reg(stk); + stk += inc_stk_for_longdouble; + } + + if (freg < num_farg_registers) { + // There are still some float argument registers left. Put the + // float in a register if not already done. + if (reg != farg_reg[freg]) { + guarantee(regs2 != NULL, "must pass float in register and stack slot"); + VMReg reg2 = farg_reg[freg]; + regs2[i].set2(reg2); + } + ++freg; + } + + regs[i].set2(reg); + break; + case T_VOID: + // Do not count halves. + regs[i].set_bad(); + --arg; + break; + default: + ShouldNotReachHere(); + } + } + + return round_to(stk, 2); +} +#endif // COMPILER2 + +static address gen_c2i_adapter(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs, + Label& call_interpreter, + const Register& ientry) { + + address c2i_entrypoint; + + const Register sender_SP = R21_sender_SP; // == R21_tmp1 + const Register code = R22_tmp2; + //const Register ientry = R23_tmp3; + const Register value_regs[] = { R24_tmp4, R25_tmp5, R26_tmp6 }; + const int num_value_regs = sizeof(value_regs) / sizeof(Register); + int value_regs_index = 0; + + const Register return_pc = R27_tmp7; + const Register tmp = R28_tmp8; + + assert_different_registers(sender_SP, code, ientry, return_pc, tmp); + + // Adapter needs TOP_IJAVA_FRAME_ABI. + const int adapter_size = frame::top_ijava_frame_abi_size + + round_to(total_args_passed * wordSize, frame::alignment_in_bytes); + + + // regular (verified) c2i entry point + c2i_entrypoint = __ pc(); + + // Does compiled code exists? If yes, patch the caller's callsite. + __ ld(code, method_(code)); + __ cmpdi(CCR0, code, 0); + __ ld(ientry, method_(interpreter_entry)); // preloaded + __ beq(CCR0, call_interpreter); + + + // Patch caller's callsite, method_(code) was not NULL which means that + // compiled code exists. + __ mflr(return_pc); + __ std(return_pc, _abi(lr), R1_SP); + RegisterSaver::push_frame_and_save_argument_registers(masm, tmp, adapter_size, total_args_passed, regs); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite), R19_method, return_pc); + + RegisterSaver::restore_argument_registers_and_pop_frame(masm, adapter_size, total_args_passed, regs); + __ ld(return_pc, _abi(lr), R1_SP); + __ ld(ientry, method_(interpreter_entry)); // preloaded + __ mtlr(return_pc); + + + // call the interpreter + __ BIND(call_interpreter); + __ mtctr(ientry); + + // Get a copy of the current SP for loading caller's arguments. + __ mr(sender_SP, R1_SP); + + // Add space for the adapter. + __ resize_frame(-adapter_size, R12_scratch2); + + int st_off = adapter_size - wordSize; + + // Write the args into the outgoing interpreter space. + for (int i = 0; i < total_args_passed; i++) { + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_stack()) { + Register tmp_reg = value_regs[value_regs_index]; + value_regs_index = (value_regs_index + 1) % num_value_regs; + // The calling convention produces OptoRegs that ignore the out + // preserve area (JIT's ABI). We must account for it here. + int ld_off = (r_1->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; + if (!r_2->is_valid()) { + __ lwz(tmp_reg, ld_off, sender_SP); + } else { + __ ld(tmp_reg, ld_off, sender_SP); + } + // Pretend stack targets were loaded into tmp_reg. + r_1 = tmp_reg->as_VMReg(); + } + + if (r_1->is_Register()) { + Register r = r_1->as_Register(); + if (!r_2->is_valid()) { + __ stw(r, st_off, R1_SP); + st_off-=wordSize; + } else { + // Longs are given 2 64-bit slots in the interpreter, but the + // data is passed in only 1 slot. + if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { + DEBUG_ONLY( __ li(tmp, 0); __ std(tmp, st_off, R1_SP); ) + st_off-=wordSize; + } + __ std(r, st_off, R1_SP); + st_off-=wordSize; + } + } else { + assert(r_1->is_FloatRegister(), ""); + FloatRegister f = r_1->as_FloatRegister(); + if (!r_2->is_valid()) { + __ stfs(f, st_off, R1_SP); + st_off-=wordSize; + } else { + // In 64bit, doubles are given 2 64-bit slots in the interpreter, but the + // data is passed in only 1 slot. + // One of these should get known junk... + DEBUG_ONLY( __ li(tmp, 0); __ std(tmp, st_off, R1_SP); ) + st_off-=wordSize; + __ stfd(f, st_off, R1_SP); + st_off-=wordSize; + } + } + } + + // Jump to the interpreter just as if interpreter was doing it. + + // load TOS + __ addi(R17_tos, R1_SP, st_off); + + // Frame_manager expects initial_caller_sp (= SP without resize by c2i) in R21_tmp1. + assert(sender_SP == R21_sender_SP, "passing initial caller's SP in wrong register"); + __ bctr(); + + return c2i_entrypoint; +} + +static void gen_i2c_adapter(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs) { + + // Load method's entry-point from methodOop. + __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); + __ mtctr(R12_scratch2); + + // We will only enter here from an interpreted frame and never from after + // passing thru a c2i. Azul allowed this but we do not. If we lose the + // race and use a c2i we will remain interpreted for the race loser(s). + // This removes all sorts of headaches on the x86 side and also eliminates + // the possibility of having c2i -> i2c -> c2i -> ... endless transitions. + + // Note: r13 contains the senderSP on entry. We must preserve it since + // we may do a i2c -> c2i transition if we lose a race where compiled + // code goes non-entrant while we get args ready. + // In addition we use r13 to locate all the interpreter args as + // we must align the stack to 16 bytes on an i2c entry else we + // lose alignment we expect in all compiled code and register + // save code can segv when fxsave instructions find improperly + // aligned stack pointer. + + const Register ld_ptr = R17_tos; + const Register value_regs[] = { R22_tmp2, R23_tmp3, R24_tmp4, R25_tmp5, R26_tmp6 }; + const int num_value_regs = sizeof(value_regs) / sizeof(Register); + int value_regs_index = 0; + + int ld_offset = total_args_passed*wordSize; + + // Cut-out for having no stack args. Since up to 2 int/oop args are passed + // in registers, we will occasionally have no stack args. + int comp_words_on_stack = 0; + if (comp_args_on_stack) { + // Sig words on the stack are greater-than VMRegImpl::stack0. Those in + // registers are below. By subtracting stack0, we either get a negative + // number (all values in registers) or the maximum stack slot accessed. + + // Convert 4-byte c2 stack slots to words. + comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + // Round up to miminum stack alignment, in wordSize. + comp_words_on_stack = round_to(comp_words_on_stack, 2); + __ resize_frame(-comp_words_on_stack * wordSize, R11_scratch1); + } + + // Now generate the shuffle code. Pick up all register args and move the + // rest through register value=Z_R12. + BLOCK_COMMENT("Shuffle arguments"); + for (int i = 0; i < total_args_passed; i++) { + if (sig_bt[i] == T_VOID) { + assert(i > 0 && (sig_bt[i-1] == T_LONG || sig_bt[i-1] == T_DOUBLE), "missing half"); + continue; + } + + // Pick up 0, 1 or 2 words from ld_ptr. + assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), + "scrambled load targets?"); + VMReg r_1 = regs[i].first(); + VMReg r_2 = regs[i].second(); + if (!r_1->is_valid()) { + assert(!r_2->is_valid(), ""); + continue; + } + if (r_1->is_FloatRegister()) { + if (!r_2->is_valid()) { + __ lfs(r_1->as_FloatRegister(), ld_offset, ld_ptr); + ld_offset-=wordSize; + } else { + // Skip the unused interpreter slot. + __ lfd(r_1->as_FloatRegister(), ld_offset-wordSize, ld_ptr); + ld_offset-=2*wordSize; + } + } else { + Register r; + if (r_1->is_stack()) { + // Must do a memory to memory move thru "value". + r = value_regs[value_regs_index]; + value_regs_index = (value_regs_index + 1) % num_value_regs; + } else { + r = r_1->as_Register(); + } + if (!r_2->is_valid()) { + // Not sure we need to do this but it shouldn't hurt. + if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ADDRESS || sig_bt[i] == T_ARRAY) { + __ ld(r, ld_offset, ld_ptr); + ld_offset-=wordSize; + } else { + __ lwz(r, ld_offset, ld_ptr); + ld_offset-=wordSize; + } + } else { + // In 64bit, longs are given 2 64-bit slots in the interpreter, but the + // data is passed in only 1 slot. + if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { + ld_offset-=wordSize; + } + __ ld(r, ld_offset, ld_ptr); + ld_offset-=wordSize; + } + + if (r_1->is_stack()) { + // Now store value where the compiler expects it + int st_off = (r_1->reg2stack() + SharedRuntime::out_preserve_stack_slots())*VMRegImpl::stack_slot_size; + + if (sig_bt[i] == T_INT || sig_bt[i] == T_FLOAT ||sig_bt[i] == T_BOOLEAN || + sig_bt[i] == T_SHORT || sig_bt[i] == T_CHAR || sig_bt[i] == T_BYTE) { + __ stw(r, st_off, R1_SP); + } else { + __ std(r, st_off, R1_SP); + } + } + } + } + + BLOCK_COMMENT("Store method oop"); + // Store method oop into thread->callee_target. + // We might end up in handle_wrong_method if the callee is + // deoptimized as we race thru here. If that happens we don't want + // to take a safepoint because the caller frame will look + // interpreted and arguments are now "compiled" so it is much better + // to make this transition invisible to the stack walking + // code. Unfortunately if we try and find the callee by normal means + // a safepoint is possible. So we stash the desired callee in the + // thread and the vm will find there should this case occur. + __ std(R19_method, thread_(callee_target)); + + // Jump to the compiled code just as if compiled code was doing it. + __ bctr(); +} + +AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs, + AdapterFingerPrint* fingerprint) { + address i2c_entry; + address c2i_unverified_entry; + address c2i_entry; + + + // entry: i2c + + __ align(CodeEntryAlignment); + i2c_entry = __ pc(); + gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); + + + // entry: c2i unverified + + __ align(CodeEntryAlignment); + BLOCK_COMMENT("c2i unverified entry"); + c2i_unverified_entry = __ pc(); + + // inline_cache contains a compiledICHolder + const Register ic = R19_method; + const Register ic_klass = R11_scratch1; + const Register receiver_klass = R12_scratch2; + const Register code = R21_tmp1; + const Register ientry = R23_tmp3; + + assert_different_registers(ic, ic_klass, receiver_klass, R3_ARG1, code, ientry); + assert(R11_scratch1 == R11, "need prologue scratch register"); + + Label call_interpreter; + + assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), + "klass offset should reach into any page"); + // Check for NULL argument if we don't have implicit null checks. + if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + __ trap_null_check(R3_ARG1); + } else { + Label valid; + __ cmpdi(CCR0, R3_ARG1, 0); + __ bne_predict_taken(CCR0, valid); + // We have a null argument, branch to ic_miss_stub. + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + __ BIND(valid); + } + } + // Assume argument is not NULL, load klass from receiver. + __ load_klass(receiver_klass, R3_ARG1); + + __ ld(ic_klass, CompiledICHolder::holder_klass_offset(), ic); + + if (TrapBasedICMissChecks) { + __ trap_ic_miss_check(receiver_klass, ic_klass); + } else { + Label valid; + __ cmpd(CCR0, receiver_klass, ic_klass); + __ beq_predict_taken(CCR0, valid); + // We have an unexpected klass, branch to ic_miss_stub. + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + __ BIND(valid); + } + + // Argument is valid and klass is as expected, continue. + + // Extract method from inline cache, verified entry point needs it. + __ ld(R19_method, CompiledICHolder::holder_method_offset(), ic); + assert(R19_method == ic, "the inline cache register is dead here"); + + __ ld(code, method_(code)); + __ cmpdi(CCR0, code, 0); + __ ld(ientry, method_(interpreter_entry)); // preloaded + __ beq_predict_taken(CCR0, call_interpreter); + + // Branch to ic_miss_stub. + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + + // entry: c2i + + c2i_entry = gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, call_interpreter, ientry); + + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); +} + +#ifdef COMPILER2 +// An oop arg. Must pass a handle not the oop itself. +static void object_move(MacroAssembler* masm, + int frame_size_in_slots, + OopMap* oop_map, int oop_handle_offset, + bool is_receiver, int* receiver_offset, + VMRegPair src, VMRegPair dst, + Register r_caller_sp, Register r_temp_1, Register r_temp_2) { + assert(!is_receiver || (is_receiver && (*receiver_offset == -1)), + "receiver has already been moved"); + + // We must pass a handle. First figure out the location we use as a handle. + + if (src.first()->is_stack()) { + // stack to stack or reg + + const Register r_handle = dst.first()->is_stack() ? r_temp_1 : dst.first()->as_Register(); + Label skip; + const int oop_slot_in_callers_frame = reg2slot(src.first()); + + guarantee(!is_receiver, "expecting receiver in register"); + oop_map->set_oop(VMRegImpl::stack2reg(oop_slot_in_callers_frame + frame_size_in_slots)); + + __ addi(r_handle, r_caller_sp, reg2offset(src.first())); + __ ld( r_temp_2, reg2offset(src.first()), r_caller_sp); + __ cmpdi(CCR0, r_temp_2, 0); + __ bne(CCR0, skip); + // Use a NULL handle if oop is NULL. + __ li(r_handle, 0); + __ bind(skip); + + if (dst.first()->is_stack()) { + // stack to stack + __ std(r_handle, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + // Nothing to do, r_handle is already the dst register. + } + } else { + // reg to stack or reg + const Register r_oop = src.first()->as_Register(); + const Register r_handle = dst.first()->is_stack() ? r_temp_1 : dst.first()->as_Register(); + const int oop_slot = (r_oop->encoding()-R3_ARG1->encoding()) * VMRegImpl::slots_per_word + + oop_handle_offset; // in slots + const int oop_offset = oop_slot * VMRegImpl::stack_slot_size; + Label skip; + + if (is_receiver) { + *receiver_offset = oop_offset; + } + oop_map->set_oop(VMRegImpl::stack2reg(oop_slot)); + + __ std( r_oop, oop_offset, R1_SP); + __ addi(r_handle, R1_SP, oop_offset); + + __ cmpdi(CCR0, r_oop, 0); + __ bne(CCR0, skip); + // Use a NULL handle if oop is NULL. + __ li(r_handle, 0); + __ bind(skip); + + if (dst.first()->is_stack()) { + // reg to stack + __ std(r_handle, reg2offset(dst.first()), R1_SP); + } else { + // reg to reg + // Nothing to do, r_handle is already the dst register. + } + } +} + +static void int_move(MacroAssembler*masm, + VMRegPair src, VMRegPair dst, + Register r_caller_sp, Register r_temp) { + assert(src.first()->is_valid() && src.second() == src.first()->next(), "incoming must be long-int"); + assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be long"); + + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ lwa(r_temp, reg2offset(src.first()), r_caller_sp); + __ std(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + __ lwa(dst.first()->as_Register(), reg2offset(src.first()), r_caller_sp); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ extsw(r_temp, src.first()->as_Register()); + __ std(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // reg to reg + __ extsw(dst.first()->as_Register(), src.first()->as_Register()); + } +} + +static void long_move(MacroAssembler*masm, + VMRegPair src, VMRegPair dst, + Register r_caller_sp, Register r_temp) { + assert(src.first()->is_valid() && src.second() == src.first()->next(), "incoming must be long"); + assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be long"); + + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld( r_temp, reg2offset(src.first()), r_caller_sp); + __ std(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + __ ld(dst.first()->as_Register(), reg2offset(src.first()), r_caller_sp); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ std(src.first()->as_Register(), reg2offset(dst.first()), R1_SP); + } else { + // reg to reg + if (dst.first()->as_Register() != src.first()->as_Register()) + __ mr(dst.first()->as_Register(), src.first()->as_Register()); + } +} + +static void float_move(MacroAssembler*masm, + VMRegPair src, VMRegPair dst, + Register r_caller_sp, Register r_temp) { + assert(src.first()->is_valid() && !src.second()->is_valid(), "incoming must be float"); + assert(dst.first()->is_valid() && !dst.second()->is_valid(), "outgoing must be float"); + + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ lwz(r_temp, reg2offset(src.first()), r_caller_sp); + __ stw(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + __ lfs(dst.first()->as_FloatRegister(), reg2offset(src.first()), r_caller_sp); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ stfs(src.first()->as_FloatRegister(), reg2offset(dst.first()), R1_SP); + } else { + // reg to reg + if (dst.first()->as_FloatRegister() != src.first()->as_FloatRegister()) + __ fmr(dst.first()->as_FloatRegister(), src.first()->as_FloatRegister()); + } +} + +static void double_move(MacroAssembler*masm, + VMRegPair src, VMRegPair dst, + Register r_caller_sp, Register r_temp) { + assert(src.first()->is_valid() && src.second() == src.first()->next(), "incoming must be double"); + assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be double"); + + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld( r_temp, reg2offset(src.first()), r_caller_sp); + __ std(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + __ lfd(dst.first()->as_FloatRegister(), reg2offset(src.first()), r_caller_sp); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ stfd(src.first()->as_FloatRegister(), reg2offset(dst.first()), R1_SP); + } else { + // reg to reg + if (dst.first()->as_FloatRegister() != src.first()->as_FloatRegister()) + __ fmr(dst.first()->as_FloatRegister(), src.first()->as_FloatRegister()); + } +} + +void SharedRuntime::save_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { + switch (ret_type) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + __ stw (R3_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_ARRAY: + case T_OBJECT: + case T_LONG: + __ std (R3_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_FLOAT: + __ stfs(F1_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_DOUBLE: + __ stfd(F1_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_VOID: + break; + default: + ShouldNotReachHere(); + break; + } +} + +void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { + switch (ret_type) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + __ lwz(R3_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_ARRAY: + case T_OBJECT: + case T_LONG: + __ ld (R3_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_FLOAT: + __ lfs(F1_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_DOUBLE: + __ lfd(F1_RET, frame_slots*VMRegImpl::stack_slot_size, R1_SP); + break; + case T_VOID: + break; + default: + ShouldNotReachHere(); + break; + } +} + +static void save_or_restore_arguments(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMap* map, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + // If map is non-NULL then the code should store the values, + // otherwise it should load them. + int slot = arg_save_area; + // Save down double word first. + for (int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_FloatRegister() && in_sig_bt[i] == T_DOUBLE) { + int offset = slot * VMRegImpl::stack_slot_size; + slot += VMRegImpl::slots_per_word; + assert(slot <= stack_slots, "overflow (after DOUBLE stack slot)"); + if (map != NULL) { + __ stfd(in_regs[i].first()->as_FloatRegister(), offset, R1_SP); + } else { + __ lfd(in_regs[i].first()->as_FloatRegister(), offset, R1_SP); + } + } else if (in_regs[i].first()->is_Register() && + (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) { + int offset = slot * VMRegImpl::stack_slot_size; + if (map != NULL) { + __ std(in_regs[i].first()->as_Register(), offset, R1_SP); + if (in_sig_bt[i] == T_ARRAY) { + map->set_oop(VMRegImpl::stack2reg(slot)); + } + } else { + __ ld(in_regs[i].first()->as_Register(), offset, R1_SP); + } + slot += VMRegImpl::slots_per_word; + assert(slot <= stack_slots, "overflow (after LONG/ARRAY stack slot)"); + } + } + // Save or restore single word registers. + for (int i = 0; i < total_in_args; i++) { + // PPC64: pass ints as longs: must only deal with floats here. + if (in_regs[i].first()->is_FloatRegister()) { + if (in_sig_bt[i] == T_FLOAT) { + int offset = slot * VMRegImpl::stack_slot_size; + slot++; + assert(slot <= stack_slots, "overflow (after FLOAT stack slot)"); + if (map != NULL) { + __ stfs(in_regs[i].first()->as_FloatRegister(), offset, R1_SP); + } else { + __ lfs(in_regs[i].first()->as_FloatRegister(), offset, R1_SP); + } + } + } else if (in_regs[i].first()->is_stack()) { + if (in_sig_bt[i] == T_ARRAY && map != NULL) { + int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); + map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); + } + } + } +} + +// Check GC_locker::needs_gc and enter the runtime if it's true. This +// keeps a new JNI critical region from starting until a GC has been +// forced. Save down any oops in registers and describe them in an +// OopMap. +static void check_needs_gc_for_critical_native(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMapSet* oop_maps, + VMRegPair* in_regs, + BasicType* in_sig_bt, + Register tmp_reg ) { + __ block_comment("check GC_locker::needs_gc"); + Label cont; + __ lbz(tmp_reg, (RegisterOrConstant)(intptr_t)GC_locker::needs_gc_address()); + __ cmplwi(CCR0, tmp_reg, 0); + __ beq(CCR0, cont); + + // Save down any values that are live in registers and call into the + // runtime to halt for a GC. + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + + __ mr(R3_ARG1, R16_thread); + __ set_last_Java_frame(R1_SP, noreg); + + __ block_comment("block_for_jni_critical"); + address entry_point = CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical); + __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, entry_point), relocInfo::runtime_call_type); + address start = __ pc() - __ offset(), + calls_return_pc = __ last_calls_return_pc(); + oop_maps->add_gc_map(calls_return_pc - start, map); + + __ reset_last_Java_frame(); + + // Reload all the register arguments. + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + + __ BIND(cont); + +#ifdef ASSERT + if (StressCriticalJNINatives) { + // Stress register saving. + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + // Destroy argument registers. + for (int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + __ neg(reg, reg); + } else if (in_regs[i].first()->is_FloatRegister()) { + __ fneg(in_regs[i].first()->as_FloatRegister(), in_regs[i].first()->as_FloatRegister()); + } + } + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + } +#endif +} + +static void move_ptr(MacroAssembler* masm, VMRegPair src, VMRegPair dst, Register r_caller_sp, Register r_temp) { + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld(r_temp, reg2offset(src.first()), r_caller_sp); + __ std(r_temp, reg2offset(dst.first()), R1_SP); + } else { + // stack to reg + __ ld(dst.first()->as_Register(), reg2offset(src.first()), r_caller_sp); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ std(src.first()->as_Register(), reg2offset(dst.first()), R1_SP); + } else { + if (dst.first() != src.first()) { + __ mr(dst.first()->as_Register(), src.first()->as_Register()); + } + } +} + +// Unpack an array argument into a pointer to the body and the length +// if the array is non-null, otherwise pass 0 for both. +static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, + VMRegPair body_arg, VMRegPair length_arg, Register r_caller_sp, + Register tmp_reg, Register tmp2_reg) { + assert(!body_arg.first()->is_Register() || body_arg.first()->as_Register() != tmp_reg, + "possible collision"); + assert(!length_arg.first()->is_Register() || length_arg.first()->as_Register() != tmp_reg, + "possible collision"); + + // Pass the length, ptr pair. + Label set_out_args; + VMRegPair tmp, tmp2; + tmp.set_ptr(tmp_reg->as_VMReg()); + tmp2.set_ptr(tmp2_reg->as_VMReg()); + if (reg.first()->is_stack()) { + // Load the arg up from the stack. + move_ptr(masm, reg, tmp, r_caller_sp, /*unused*/ R0); + reg = tmp; + } + __ li(tmp2_reg, 0); // Pass zeros if Array=null. + if (tmp_reg != reg.first()->as_Register()) __ li(tmp_reg, 0); + __ cmpdi(CCR0, reg.first()->as_Register(), 0); + __ beq(CCR0, set_out_args); + __ lwa(tmp2_reg, arrayOopDesc::length_offset_in_bytes(), reg.first()->as_Register()); + __ addi(tmp_reg, reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type)); + __ bind(set_out_args); + move_ptr(masm, tmp, body_arg, r_caller_sp, /*unused*/ R0); + move_ptr(masm, tmp2, length_arg, r_caller_sp, /*unused*/ R0); // Same as move32_64 on PPC64. +} + +static void verify_oop_args(MacroAssembler* masm, + methodHandle method, + const BasicType* sig_bt, + const VMRegPair* regs) { + Register temp_reg = R19_method; // not part of any compiled calling seq + if (VerifyOops) { + for (int i = 0; i < method->size_of_parameters(); i++) { + if (sig_bt[i] == T_OBJECT || + sig_bt[i] == T_ARRAY) { + VMReg r = regs[i].first(); + assert(r->is_valid(), "bad oop arg"); + if (r->is_stack()) { + __ ld(temp_reg, reg2offset(r), R1_SP); + __ verify_oop(temp_reg); + } else { + __ verify_oop(r->as_Register()); + } + } + } + } +} + +static void gen_special_dispatch(MacroAssembler* masm, + methodHandle method, + const BasicType* sig_bt, + const VMRegPair* regs) { + verify_oop_args(masm, method, sig_bt, regs); + vmIntrinsics::ID iid = method->intrinsic_id(); + + // Now write the args into the outgoing interpreter space + bool has_receiver = false; + Register receiver_reg = noreg; + int member_arg_pos = -1; + Register member_reg = noreg; + int ref_kind = MethodHandles::signature_polymorphic_intrinsic_ref_kind(iid); + if (ref_kind != 0) { + member_arg_pos = method->size_of_parameters() - 1; // trailing MemberName argument + member_reg = R19_method; // known to be free at this point + has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); + } else if (iid == vmIntrinsics::_invokeBasic) { + has_receiver = true; + } else { + fatal(err_msg_res("unexpected intrinsic id %d", iid)); + } + + if (member_reg != noreg) { + // Load the member_arg into register, if necessary. + SharedRuntime::check_member_name_argument_is_last_argument(method, sig_bt, regs); + VMReg r = regs[member_arg_pos].first(); + if (r->is_stack()) { + __ ld(member_reg, reg2offset(r), R1_SP); + } else { + // no data motion is needed + member_reg = r->as_Register(); + } + } + + if (has_receiver) { + // Make sure the receiver is loaded into a register. + assert(method->size_of_parameters() > 0, "oob"); + assert(sig_bt[0] == T_OBJECT, "receiver argument must be an object"); + VMReg r = regs[0].first(); + assert(r->is_valid(), "bad receiver arg"); + if (r->is_stack()) { + // Porting note: This assumes that compiled calling conventions always + // pass the receiver oop in a register. If this is not true on some + // platform, pick a temp and load the receiver from stack. + fatal("receiver always in a register"); + receiver_reg = R11_scratch1; // TODO (hs24): is R11_scratch1 really free at this point? + __ ld(receiver_reg, reg2offset(r), R1_SP); + } else { + // no data motion is needed + receiver_reg = r->as_Register(); + } + } + + // Figure out which address we are really jumping to: + MethodHandles::generate_method_handle_dispatch(masm, iid, + receiver_reg, member_reg, /*for_compiler_entry:*/ true); +} + +#endif // COMPILER2 + +// --------------------------------------------------------------------------- +// Generate a native wrapper for a given method. The method takes arguments +// in the Java compiled code convention, marshals them to the native +// convention (handlizes oops, etc), transitions to native, makes the call, +// returns to java state (possibly blocking), unhandlizes any result and +// returns. +// +// Critical native functions are a shorthand for the use of +// GetPrimtiveArrayCritical and disallow the use of any other JNI +// functions. The wrapper is expected to unpack the arguments before +// passing them to the callee and perform checks before and after the +// native call to ensure that they GC_locker +// lock_critical/unlock_critical semantics are followed. Some other +// parts of JNI setup are skipped like the tear down of the JNI handle +// block and the check for pending exceptions it's impossible for them +// to be thrown. +// +// They are roughly structured like this: +// if (GC_locker::needs_gc()) +// SharedRuntime::block_for_jni_critical(); +// tranistion to thread_in_native +// unpack arrray arguments and call native entry point +// check for safepoint in progress +// check if any thread suspend flags are set +// call into JVM and possible unlock the JNI critical +// if a GC was suppressed while in the critical native. +// transition back to thread_in_Java +// return to caller +// +nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, + methodHandle method, + int compile_id, + BasicType *in_sig_bt, + VMRegPair *in_regs, + BasicType ret_type) { +#ifdef COMPILER2 + if (method->is_method_handle_intrinsic()) { + vmIntrinsics::ID iid = method->intrinsic_id(); + intptr_t start = (intptr_t)__ pc(); + int vep_offset = ((intptr_t)__ pc()) - start; + gen_special_dispatch(masm, + method, + in_sig_bt, + in_regs); + int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period + __ flush(); + int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually + return nmethod::new_native_nmethod(method, + compile_id, + masm->code(), + vep_offset, + frame_complete, + stack_slots / VMRegImpl::slots_per_word, + in_ByteSize(-1), + in_ByteSize(-1), + (OopMapSet*)NULL); + } + + bool is_critical_native = true; + address native_func = method->critical_native_function(); + if (native_func == NULL) { + native_func = method->native_function(); + is_critical_native = false; + } + assert(native_func != NULL, "must have function"); + + // First, create signature for outgoing C call + // -------------------------------------------------------------------------- + + int total_in_args = method->size_of_parameters(); + // We have received a description of where all the java args are located + // on entry to the wrapper. We need to convert these args to where + // the jni function will expect them. To figure out where they go + // we convert the java signature to a C signature by inserting + // the hidden arguments as arg[0] and possibly arg[1] (static method) + // + // Additionally, on ppc64 we must convert integers to longs in the C + // signature. We do this in advance in order to have no trouble with + // indexes into the bt-arrays. + // So convert the signature and registers now, and adjust the total number + // of in-arguments accordingly. + int i2l_argcnt = convert_ints_to_longints_argcnt(total_in_args, in_sig_bt); // PPC64: pass ints as longs. + + // Calculate the total number of C arguments and create arrays for the + // signature and the outgoing registers. + // On ppc64, we have two arrays for the outgoing registers, because + // some floating-point arguments must be passed in registers _and_ + // in stack locations. + bool method_is_static = method->is_static(); + int total_c_args = i2l_argcnt; + + if (!is_critical_native) { + int n_hidden_args = method_is_static ? 2 : 1; + total_c_args += n_hidden_args; + } else { + // No JNIEnv*, no this*, but unpacked arrays (base+length). + for (int i = 0; i < total_in_args; i++) { + if (in_sig_bt[i] == T_ARRAY) { + total_c_args += 2; // PPC64: T_LONG, T_INT, T_ADDRESS (see convert_ints_to_longints and c_calling_convention) + } + } + } + + BasicType *out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); + VMRegPair *out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + VMRegPair *out_regs2 = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + BasicType* in_elem_bt = NULL; + + // Create the signature for the C call: + // 1) add the JNIEnv* + // 2) add the class if the method is static + // 3) copy the rest of the incoming signature (shifted by the number of + // hidden arguments). + + int argc = 0; + if (!is_critical_native) { + convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs. + + out_sig_bt[argc++] = T_ADDRESS; + if (method->is_static()) { + out_sig_bt[argc++] = T_OBJECT; + } + + for (int i = 0; i < total_in_args ; i++ ) { + out_sig_bt[argc++] = in_sig_bt[i]; + } + } else { + Thread* THREAD = Thread::current(); + in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); + SignatureStream ss(method->signature()); + int o = 0; + for (int i = 0; i < total_in_args ; i++, o++) { + if (in_sig_bt[i] == T_ARRAY) { + // Arrays are passed as int, elem* pair + Symbol* atype = ss.as_symbol(CHECK_NULL); + const char* at = atype->as_C_string(); + if (strlen(at) == 2) { + assert(at[0] == '[', "must be"); + switch (at[1]) { + case 'B': in_elem_bt[o] = T_BYTE; break; + case 'C': in_elem_bt[o] = T_CHAR; break; + case 'D': in_elem_bt[o] = T_DOUBLE; break; + case 'F': in_elem_bt[o] = T_FLOAT; break; + case 'I': in_elem_bt[o] = T_INT; break; + case 'J': in_elem_bt[o] = T_LONG; break; + case 'S': in_elem_bt[o] = T_SHORT; break; + case 'Z': in_elem_bt[o] = T_BOOLEAN; break; + default: ShouldNotReachHere(); + } + } + } else { + in_elem_bt[o] = T_VOID; + switch(in_sig_bt[i]) { // PPC64: pass ints as longs. + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: in_elem_bt[++o] = T_VOID; break; + default: break; + } + } + if (in_sig_bt[i] != T_VOID) { + assert(in_sig_bt[i] == ss.type(), "must match"); + ss.next(); + } + } + assert(i2l_argcnt==o, "must match"); + + convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs. + + for (int i = 0; i < total_in_args ; i++ ) { + if (in_sig_bt[i] == T_ARRAY) { + // Arrays are passed as int, elem* pair. + out_sig_bt[argc++] = T_LONG; // PPC64: pass ints as longs. + out_sig_bt[argc++] = T_INT; + out_sig_bt[argc++] = T_ADDRESS; + } else { + out_sig_bt[argc++] = in_sig_bt[i]; + } + } + } + + + // Compute the wrapper's frame size. + // -------------------------------------------------------------------------- + + // Now figure out where the args must be stored and how much stack space + // they require. + // + // Compute framesize for the wrapper. We need to handlize all oops in + // incoming registers. + // + // Calculate the total number of stack slots we will need: + // 1) abi requirements + // 2) outgoing arguments + // 3) space for inbound oop handle area + // 4) space for handlizing a klass if static method + // 5) space for a lock if synchronized method + // 6) workspace for saving return values, int <-> float reg moves, etc. + // 7) alignment + // + // Layout of the native wrapper frame: + // (stack grows upwards, memory grows downwards) + // + // NW [ABI_112] <-- 1) R1_SP + // [outgoing arguments] <-- 2) R1_SP + out_arg_slot_offset + // [oopHandle area] <-- 3) R1_SP + oop_handle_offset (save area for critical natives) + // klass <-- 4) R1_SP + klass_offset + // lock <-- 5) R1_SP + lock_offset + // [workspace] <-- 6) R1_SP + workspace_offset + // [alignment] (optional) <-- 7) + // caller [JIT_TOP_ABI_48] <-- r_callers_sp + // + // - *_slot_offset Indicates offset from SP in number of stack slots. + // - *_offset Indicates offset from SP in bytes. + + int stack_slots = c_calling_convention(out_sig_bt, out_regs, out_regs2, total_c_args) // 1+2) + + SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention. + + // Now the space for the inbound oop handle area. + int total_save_slots = num_java_iarg_registers * VMRegImpl::slots_per_word; + if (is_critical_native) { + // Critical natives may have to call out so they need a save area + // for register arguments. + int double_slots = 0; + int single_slots = 0; + for (int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_BOOLEAN: + case T_BYTE: + case T_SHORT: + case T_CHAR: + case T_INT: /*single_slots++;*/ break; // PPC64: pass ints as longs. + case T_ARRAY: + case T_LONG: double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_FloatRegister()) { + switch (in_sig_bt[i]) { + case T_FLOAT: single_slots++; break; + case T_DOUBLE: double_slots++; break; + default: ShouldNotReachHere(); + } + } + } + total_save_slots = double_slots * 2 + round_to(single_slots, 2); // round to even + } + + int oop_handle_slot_offset = stack_slots; + stack_slots += total_save_slots; // 3) + + int klass_slot_offset = 0; + int klass_offset = -1; + if (method_is_static && !is_critical_native) { // 4) + klass_slot_offset = stack_slots; + klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; + stack_slots += VMRegImpl::slots_per_word; + } + + int lock_slot_offset = 0; + int lock_offset = -1; + if (method->is_synchronized()) { // 5) + lock_slot_offset = stack_slots; + lock_offset = lock_slot_offset * VMRegImpl::stack_slot_size; + stack_slots += VMRegImpl::slots_per_word; + } + + int workspace_slot_offset = stack_slots; // 6) + stack_slots += 2; + + // Now compute actual number of stack words we need. + // Rounding to make stack properly aligned. + stack_slots = round_to(stack_slots, // 7) + frame::alignment_in_bytes / VMRegImpl::stack_slot_size); + int frame_size_in_bytes = stack_slots * VMRegImpl::stack_slot_size; + + + // Now we can start generating code. + // -------------------------------------------------------------------------- + + intptr_t start_pc = (intptr_t)__ pc(); + intptr_t vep_start_pc; + intptr_t frame_done_pc; + intptr_t oopmap_pc; + + Label ic_miss; + Label handle_pending_exception; + + Register r_callers_sp = R21; + Register r_temp_1 = R22; + Register r_temp_2 = R23; + Register r_temp_3 = R24; + Register r_temp_4 = R25; + Register r_temp_5 = R26; + Register r_temp_6 = R27; + Register r_return_pc = R28; + + Register r_carg1_jnienv = noreg; + Register r_carg2_classorobject = noreg; + if (!is_critical_native) { + r_carg1_jnienv = out_regs[0].first()->as_Register(); + r_carg2_classorobject = out_regs[1].first()->as_Register(); + } + + + // Generate the Unverified Entry Point (UEP). + // -------------------------------------------------------------------------- + assert(start_pc == (intptr_t)__ pc(), "uep must be at start"); + + // Check ic: object class == cached class? + if (!method_is_static) { + Register ic = as_Register(Matcher::inline_cache_reg_encode()); + Register receiver_klass = r_temp_1; + + __ cmpdi(CCR0, R3_ARG1, 0); + __ beq(CCR0, ic_miss); + __ verify_oop(R3_ARG1); + __ load_klass(receiver_klass, R3_ARG1); + + __ cmpd(CCR0, receiver_klass, ic); + __ bne(CCR0, ic_miss); + } + + + // Generate the Verified Entry Point (VEP). + // -------------------------------------------------------------------------- + vep_start_pc = (intptr_t)__ pc(); + + __ save_LR_CR(r_temp_1); + __ generate_stack_overflow_check(frame_size_in_bytes); // Check before creating frame. + __ mr(r_callers_sp, R1_SP); // Remember frame pointer. + __ push_frame(frame_size_in_bytes, r_temp_1); // Push the c2n adapter's frame. + frame_done_pc = (intptr_t)__ pc(); + + // Native nmethod wrappers never take possesion of the oop arguments. + // So the caller will gc the arguments. + // The only thing we need an oopMap for is if the call is static. + // + // An OopMap for lock (and class if static), and one for the VM call itself. + OopMapSet *oop_maps = new OopMapSet(); + OopMap *oop_map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + + if (is_critical_native) { + check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, oop_handle_slot_offset, oop_maps, in_regs, in_sig_bt, r_temp_1); + } + + // Move arguments from register/stack to register/stack. + // -------------------------------------------------------------------------- + // + // We immediately shuffle the arguments so that for any vm call we have + // to make from here on out (sync slow path, jvmti, etc.) we will have + // captured the oops from our caller and have a valid oopMap for them. + // + // Natives require 1 or 2 extra arguments over the normal ones: the JNIEnv* + // (derived from JavaThread* which is in R16_thread) and, if static, + // the class mirror instead of a receiver. This pretty much guarantees that + // register layout will not match. We ignore these extra arguments during + // the shuffle. The shuffle is described by the two calling convention + // vectors we have in our possession. We simply walk the java vector to + // get the source locations and the c vector to get the destinations. + + // Record sp-based slot for receiver on stack for non-static methods. + int receiver_offset = -1; + + // We move the arguments backward because the floating point registers + // destination will always be to a register with a greater or equal + // register number or the stack. + // in is the index of the incoming Java arguments + // out is the index of the outgoing C arguments + +#ifdef ASSERT + bool reg_destroyed[RegisterImpl::number_of_registers]; + bool freg_destroyed[FloatRegisterImpl::number_of_registers]; + for (int r = 0 ; r < RegisterImpl::number_of_registers ; r++) { + reg_destroyed[r] = false; + } + for (int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++) { + freg_destroyed[f] = false; + } +#endif // ASSERT + + for (int in = total_in_args - 1, out = total_c_args - 1; in >= 0 ; in--, out--) { + +#ifdef ASSERT + if (in_regs[in].first()->is_Register()) { + assert(!reg_destroyed[in_regs[in].first()->as_Register()->encoding()], "ack!"); + } else if (in_regs[in].first()->is_FloatRegister()) { + assert(!freg_destroyed[in_regs[in].first()->as_FloatRegister()->encoding()], "ack!"); + } + if (out_regs[out].first()->is_Register()) { + reg_destroyed[out_regs[out].first()->as_Register()->encoding()] = true; + } else if (out_regs[out].first()->is_FloatRegister()) { + freg_destroyed[out_regs[out].first()->as_FloatRegister()->encoding()] = true; + } + if (out_regs2[out].first()->is_Register()) { + reg_destroyed[out_regs2[out].first()->as_Register()->encoding()] = true; + } else if (out_regs2[out].first()->is_FloatRegister()) { + freg_destroyed[out_regs2[out].first()->as_FloatRegister()->encoding()] = true; + } +#endif // ASSERT + + switch (in_sig_bt[in]) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + guarantee(in > 0 && in_sig_bt[in-1] == T_LONG, + "expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); + break; + case T_LONG: + if (in_sig_bt[in+1] == T_VOID) { + long_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); + } else { + guarantee(in_sig_bt[in+1] == T_BOOLEAN || in_sig_bt[in+1] == T_CHAR || + in_sig_bt[in+1] == T_BYTE || in_sig_bt[in+1] == T_SHORT || + in_sig_bt[in+1] == T_INT, + "expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); + int_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); + } + break; + case T_ARRAY: + if (is_critical_native) { + int body_arg = out; + out -= 2; // Point to length arg. PPC64: pass ints as longs. + unpack_array_argument(masm, in_regs[in], in_elem_bt[in], out_regs[body_arg], out_regs[out], + r_callers_sp, r_temp_1, r_temp_2); + break; + } + case T_OBJECT: + assert(!is_critical_native, "no oop arguments"); + object_move(masm, stack_slots, + oop_map, oop_handle_slot_offset, + ((in == 0) && (!method_is_static)), &receiver_offset, + in_regs[in], out_regs[out], + r_callers_sp, r_temp_1, r_temp_2); + break; + case T_VOID: + break; + case T_FLOAT: + float_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); + if (out_regs2[out].first()->is_valid()) { + float_move(masm, in_regs[in], out_regs2[out], r_callers_sp, r_temp_1); + } + break; + case T_DOUBLE: + double_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); + if (out_regs2[out].first()->is_valid()) { + double_move(masm, in_regs[in], out_regs2[out], r_callers_sp, r_temp_1); + } + break; + case T_ADDRESS: + fatal("found type (T_ADDRESS) in java args"); + break; + default: + ShouldNotReachHere(); + break; + } + } + + // Pre-load a static method's oop into ARG2. + // Used both by locking code and the normal JNI call code. + if (method_is_static && !is_critical_native) { + __ set_oop_constant(JNIHandles::make_local(method->method_holder()->java_mirror()), + r_carg2_classorobject); + + // Now handlize the static class mirror in carg2. It's known not-null. + __ std(r_carg2_classorobject, klass_offset, R1_SP); + oop_map->set_oop(VMRegImpl::stack2reg(klass_slot_offset)); + __ addi(r_carg2_classorobject, R1_SP, klass_offset); + } + + // Get JNIEnv* which is first argument to native. + if (!is_critical_native) { + __ addi(r_carg1_jnienv, R16_thread, in_bytes(JavaThread::jni_environment_offset())); + } + + // NOTE: + // + // We have all of the arguments setup at this point. + // We MUST NOT touch any outgoing regs from this point on. + // So if we must call out we must push a new frame. + + // Get current pc for oopmap, and load it patchable relative to global toc. + oopmap_pc = (intptr_t) __ pc(); + __ calculate_address_from_global_toc(r_return_pc, (address)oopmap_pc, true, true, true, true); + + // We use the same pc/oopMap repeatedly when we call out. + oop_maps->add_gc_map(oopmap_pc - start_pc, oop_map); + + // r_return_pc now has the pc loaded that we will use when we finally call + // to native. + + // Make sure that thread is non-volatile; it crosses a bunch of VM calls below. + assert(R16_thread->is_nonvolatile(), "thread must be in non-volatile register"); + + +# if 0 + // DTrace method entry +# endif + + // Lock a synchronized method. + // -------------------------------------------------------------------------- + + if (method->is_synchronized()) { + assert(!is_critical_native, "unhandled"); + ConditionRegister r_flag = CCR1; + Register r_oop = r_temp_4; + const Register r_box = r_temp_5; + Label done, locked; + + // Load the oop for the object or class. r_carg2_classorobject contains + // either the handlized oop from the incoming arguments or the handlized + // class mirror (if the method is static). + __ ld(r_oop, 0, r_carg2_classorobject); + + // Get the lock box slot's address. + __ addi(r_box, R1_SP, lock_offset); + +# ifdef ASSERT + if (UseBiasedLocking) { + // Making the box point to itself will make it clear it went unused + // but also be obviously invalid. + __ std(r_box, 0, r_box); + } +# endif // ASSERT + + // Try fastpath for locking. + // fast_lock kills r_temp_1, r_temp_2, r_temp_3. + __ compiler_fast_lock_object(r_flag, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3); + __ beq(r_flag, locked); + + // None of the above fast optimizations worked so we have to get into the + // slow case of monitor enter. Inline a special case of call_VM that + // disallows any pending_exception. + + // Save argument registers and leave room for C-compatible ABI_112. + int frame_size = frame::abi_112_size + + round_to(total_c_args * wordSize, frame::alignment_in_bytes); + __ mr(R11_scratch1, R1_SP); + RegisterSaver::push_frame_and_save_argument_registers(masm, R12_scratch2, frame_size, total_c_args, out_regs, out_regs2); + + // Do the call. + __ set_last_Java_frame(R11_scratch1, r_return_pc); + assert(r_return_pc->is_nonvolatile(), "expecting return pc to be in non-volatile register"); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), r_oop, r_box, R16_thread); + __ reset_last_Java_frame(); + + RegisterSaver::restore_argument_registers_and_pop_frame(masm, frame_size, total_c_args, out_regs, out_regs2); + + __ asm_assert_mem8_is_zero(thread_(pending_exception), + "no pending exception allowed on exit from SharedRuntime::complete_monitor_locking_C", 0); + + __ bind(locked); + } + + + // Publish thread state + // -------------------------------------------------------------------------- + + // Use that pc we placed in r_return_pc a while back as the current frame anchor. + __ set_last_Java_frame(R1_SP, r_return_pc); + + // Transition from _thread_in_Java to _thread_in_native. + __ li(R0, _thread_in_native); + __ release(); + // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); + __ stw(R0, thread_(thread_state)); + if (UseMembar) { + __ fence(); + } + + + // The JNI call + // -------------------------------------------------------------------------- + + FunctionDescriptor* fd_native_method = (FunctionDescriptor*) native_func; + __ call_c(fd_native_method, relocInfo::runtime_call_type); + + + // Now, we are back from the native code. + + + // Unpack the native result. + // -------------------------------------------------------------------------- + + // For int-types, we do any needed sign-extension required. + // Care must be taken that the return values (R3_RET and F1_RET) + // will survive any VM calls for blocking or unlocking. + // An OOP result (handle) is done specially in the slow-path code. + + switch (ret_type) { + case T_VOID: break; // Nothing to do! + case T_FLOAT: break; // Got it where we want it (unless slow-path). + case T_DOUBLE: break; // Got it where we want it (unless slow-path). + case T_LONG: break; // Got it where we want it (unless slow-path). + case T_OBJECT: break; // Really a handle. + // Cannot de-handlize until after reclaiming jvm_lock. + case T_ARRAY: break; + + case T_BOOLEAN: { // 0 -> false(0); !0 -> true(1) + Label skip_modify; + __ cmpwi(CCR0, R3_RET, 0); + __ beq(CCR0, skip_modify); + __ li(R3_RET, 1); + __ bind(skip_modify); + break; + } + case T_BYTE: { // sign extension + __ extsb(R3_RET, R3_RET); + break; + } + case T_CHAR: { // unsigned result + __ andi(R3_RET, R3_RET, 0xffff); + break; + } + case T_SHORT: { // sign extension + __ extsh(R3_RET, R3_RET); + break; + } + case T_INT: // nothing to do + break; + default: + ShouldNotReachHere(); + break; + } + + + // Publish thread state + // -------------------------------------------------------------------------- + + // Switch thread to "native transition" state before reading the + // synchronization state. This additional state is necessary because reading + // and testing the synchronization state is not atomic w.r.t. GC, as this + // scenario demonstrates: + // - Java thread A, in _thread_in_native state, loads _not_synchronized + // and is preempted. + // - VM thread changes sync state to synchronizing and suspends threads + // for GC. + // - Thread A is resumed to finish this native method, but doesn't block + // here since it didn't see any synchronization in progress, and escapes. + + // Transition from _thread_in_native to _thread_in_native_trans. + __ li(R0, _thread_in_native_trans); + __ release(); + // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); + __ stw(R0, thread_(thread_state)); + + + // Must we block? + // -------------------------------------------------------------------------- + + // Block, if necessary, before resuming in _thread_in_Java state. + // In order for GC to work, don't clear the last_Java_sp until after blocking. + Label after_transition; + { + Label no_block, sync; + + if (os::is_MP()) { + if (UseMembar) { + // Force this write out before the read below. + __ fence(); + } else { + // Write serialization page so VM thread can do a pseudo remote membar. + // We use the current thread pointer to calculate a thread specific + // offset to write to within the page. This minimizes bus traffic + // due to cache line collision. + __ serialize_memory(R16_thread, r_temp_4, r_temp_5); + } + } + + Register sync_state_addr = r_temp_4; + Register sync_state = r_temp_5; + Register suspend_flags = r_temp_6; + + __ load_const(sync_state_addr, SafepointSynchronize::address_of_state(), /*temp*/ sync_state); + + // TODO: PPC port assert(4 == SafepointSynchronize::sz_state(), "unexpected field size"); + __ lwz(sync_state, 0, sync_state_addr); + + // TODO: PPC port assert(4 == Thread::sz_suspend_flags(), "unexpected field size"); + __ lwz(suspend_flags, thread_(suspend_flags)); + + __ acquire(); + + Label do_safepoint; + // No synchronization in progress nor yet synchronized. + __ cmpwi(CCR0, sync_state, SafepointSynchronize::_not_synchronized); + // Not suspended. + __ cmpwi(CCR1, suspend_flags, 0); + + __ bne(CCR0, sync); + __ beq(CCR1, no_block); + + // Block. Save any potential method result value before the operation and + // use a leaf call to leave the last_Java_frame setup undisturbed. Doing this + // lets us share the oopMap we used when we went native rather than create + // a distinct one for this pc. + __ bind(sync); + + address entry_point = is_critical_native + ? CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition) + : CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans); + save_native_result(masm, ret_type, workspace_slot_offset); + __ call_VM_leaf(entry_point, R16_thread); + restore_native_result(masm, ret_type, workspace_slot_offset); + + if (is_critical_native) { + __ b(after_transition); // No thread state transition here. + } + __ bind(no_block); + } + + // Publish thread state. + // -------------------------------------------------------------------------- + + // Thread state is thread_in_native_trans. Any safepoint blocking has + // already happened so we can now change state to _thread_in_Java. + + // Transition from _thread_in_native_trans to _thread_in_Java. + __ li(R0, _thread_in_Java); + __ release(); + // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size"); + __ stw(R0, thread_(thread_state)); + if (UseMembar) { + __ fence(); + } + __ bind(after_transition); + + // Reguard any pages if necessary. + // -------------------------------------------------------------------------- + + Label no_reguard; + __ lwz(r_temp_1, thread_(stack_guard_state)); + __ cmpwi(CCR0, r_temp_1, JavaThread::stack_guard_yellow_disabled); + __ bne(CCR0, no_reguard); + + save_native_result(masm, ret_type, workspace_slot_offset); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); + restore_native_result(masm, ret_type, workspace_slot_offset); + + __ bind(no_reguard); + + + // Unlock + // -------------------------------------------------------------------------- + + if (method->is_synchronized()) { + + ConditionRegister r_flag = CCR1; + const Register r_oop = r_temp_4; + const Register r_box = r_temp_5; + const Register r_exception = r_temp_6; + Label done; + + // Get oop and address of lock object box. + if (method_is_static) { + assert(klass_offset != -1, ""); + __ ld(r_oop, klass_offset, R1_SP); + } else { + assert(receiver_offset != -1, ""); + __ ld(r_oop, receiver_offset, R1_SP); + } + __ addi(r_box, R1_SP, lock_offset); + + // Try fastpath for unlocking. + __ compiler_fast_unlock_object(r_flag, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3); + __ beq(r_flag, done); + + // Save and restore any potential method result value around the unlocking operation. + save_native_result(masm, ret_type, workspace_slot_offset); + + // Must save pending exception around the slow-path VM call. Since it's a + // leaf call, the pending exception (if any) can be kept in a register. + __ ld(r_exception, thread_(pending_exception)); + assert(r_exception->is_nonvolatile(), "exception register must be non-volatile"); + __ li(R0, 0); + __ std(R0, thread_(pending_exception)); + + // Slow case of monitor enter. + // Inline a special case of call_VM that disallows any pending_exception. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), r_oop, r_box); + + __ asm_assert_mem8_is_zero(thread_(pending_exception), + "no pending exception allowed on exit from SharedRuntime::complete_monitor_unlocking_C", 0); + + restore_native_result(masm, ret_type, workspace_slot_offset); + + // Check_forward_pending_exception jump to forward_exception if any pending + // exception is set. The forward_exception routine expects to see the + // exception in pending_exception and not in a register. Kind of clumsy, + // since all folks who branch to forward_exception must have tested + // pending_exception first and hence have it in a register already. + __ std(r_exception, thread_(pending_exception)); + + __ bind(done); + } + +# if 0 + // DTrace method exit +# endif + + // Clear "last Java frame" SP and PC. + // -------------------------------------------------------------------------- + + __ reset_last_Java_frame(); + + // Unpack oop result. + // -------------------------------------------------------------------------- + + if (ret_type == T_OBJECT || ret_type == T_ARRAY) { + Label skip_unboxing; + __ cmpdi(CCR0, R3_RET, 0); + __ beq(CCR0, skip_unboxing); + __ ld(R3_RET, 0, R3_RET); + __ bind(skip_unboxing); + __ verify_oop(R3_RET); + } + + + // Reset handle block. + // -------------------------------------------------------------------------- + if (!is_critical_native) { + __ ld(r_temp_1, thread_(active_handles)); + // TODO: PPC port assert(4 == JNIHandleBlock::top_size_in_bytes(), "unexpected field size"); + __ li(r_temp_2, 0); + __ stw(r_temp_2, JNIHandleBlock::top_offset_in_bytes(), r_temp_1); + + + // Check for pending exceptions. + // -------------------------------------------------------------------------- + __ ld(r_temp_2, thread_(pending_exception)); + __ cmpdi(CCR0, r_temp_2, 0); + __ bne(CCR0, handle_pending_exception); + } + + // Return + // -------------------------------------------------------------------------- + + __ pop_frame(); + __ restore_LR_CR(R11); + __ blr(); + + + // Handler for pending exceptions (out-of-line). + // -------------------------------------------------------------------------- + + // Since this is a native call, we know the proper exception handler + // is the empty function. We just pop this frame and then jump to + // forward_exception_entry. + if (!is_critical_native) { + __ align(InteriorEntryAlignment); + __ bind(handle_pending_exception); + + __ pop_frame(); + __ restore_LR_CR(R11); + __ b64_patchable((address)StubRoutines::forward_exception_entry(), + relocInfo::runtime_call_type); + } + + // Handler for a cache miss (out-of-line). + // -------------------------------------------------------------------------- + + if (!method_is_static) { + __ align(InteriorEntryAlignment); + __ bind(ic_miss); + + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + } + + // Done. + // -------------------------------------------------------------------------- + + __ flush(); + + nmethod *nm = nmethod::new_native_nmethod(method, + compile_id, + masm->code(), + vep_start_pc-start_pc, + frame_done_pc-start_pc, + stack_slots / VMRegImpl::slots_per_word, + (method_is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), + in_ByteSize(lock_offset), + oop_maps); + + if (is_critical_native) { + nm->set_lazy_critical_native(true); + } + + return nm; +#else + ShouldNotReachHere(); + return NULL; +#endif // COMPILER2 +} + +// This function returns the adjust size (in number of words) to a c2i adapter +// activation for use during deoptimization. +int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { + return round_to((callee_locals - callee_parameters) * Interpreter::stackElementWords, frame::alignment_in_bytes); +} + +uint SharedRuntime::out_preserve_stack_slots() { +#ifdef COMPILER2 + return frame::jit_out_preserve_size / VMRegImpl::stack_slot_size; +#else + return 0; +#endif +} + +#ifdef COMPILER2 +// Frame generation for deopt and uncommon trap blobs. +static void push_skeleton_frame(MacroAssembler* masm, bool deopt, + /* Read */ + Register unroll_block_reg, + /* Update */ + Register frame_sizes_reg, + Register number_of_frames_reg, + Register pcs_reg, + /* Invalidate */ + Register frame_size_reg, + Register pc_reg) { + + __ ld(pc_reg, 0, pcs_reg); + __ ld(frame_size_reg, 0, frame_sizes_reg); + __ std(pc_reg, _abi(lr), R1_SP); + __ push_frame(frame_size_reg, R0/*tmp*/); + __ std(R1_SP, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); + __ addi(number_of_frames_reg, number_of_frames_reg, -1); + __ addi(frame_sizes_reg, frame_sizes_reg, wordSize); + __ addi(pcs_reg, pcs_reg, wordSize); +} + +// Loop through the UnrollBlock info and create new frames. +static void push_skeleton_frames(MacroAssembler* masm, bool deopt, + /* read */ + Register unroll_block_reg, + /* invalidate */ + Register frame_sizes_reg, + Register number_of_frames_reg, + Register pcs_reg, + Register frame_size_reg, + Register pc_reg) { + Label loop; + + // _number_of_frames is of type int (deoptimization.hpp) + __ lwa(number_of_frames_reg, + Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), + unroll_block_reg); + __ ld(pcs_reg, + Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), + unroll_block_reg); + __ ld(frame_sizes_reg, + Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes(), + unroll_block_reg); + + // stack: (caller_of_deoptee, ...). + + // At this point we either have an interpreter frame or a compiled + // frame on top of stack. If it is a compiled frame we push a new c2i + // adapter here + + // Memorize top-frame stack-pointer. + __ mr(frame_size_reg/*old_sp*/, R1_SP); + + // Resize interpreter top frame OR C2I adapter. + + // At this moment, the top frame (which is the caller of the deoptee) is + // an interpreter frame or a newly pushed C2I adapter or an entry frame. + // The top frame has a TOP_IJAVA_FRAME_ABI and the frame contains the + // outgoing arguments. + // + // In order to push the interpreter frame for the deoptee, we need to + // resize the top frame such that we are able to place the deoptee's + // locals in the frame. + // Additionally, we have to turn the top frame's TOP_IJAVA_FRAME_ABI + // into a valid PARENT_IJAVA_FRAME_ABI. + + __ lwa(R11_scratch1, + Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes(), + unroll_block_reg); + __ neg(R11_scratch1, R11_scratch1); + + // R11_scratch1 contains size of locals for frame resizing. + // R12_scratch2 contains top frame's lr. + + // Resize frame by complete frame size prevents TOC from being + // overwritten by locals. A more stack space saving way would be + // to copy the TOC to its location in the new abi. + __ addi(R11_scratch1, R11_scratch1, - frame::parent_ijava_frame_abi_size); + + // now, resize the frame + __ resize_frame(R11_scratch1, pc_reg/*tmp*/); + + // In the case where we have resized a c2i frame above, the optional + // alignment below the locals has size 32 (why?). + __ std(R12_scratch2, _abi(lr), R1_SP); + + // Initialize initial_caller_sp. + __ std(frame_size_reg/*old_sp*/, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); + +#ifdef ASSERT + // Make sure that there is at least one entry in the array. + __ cmpdi(CCR0, number_of_frames_reg, 0); + __ asm_assert_ne("array_size must be > 0", 0x205); +#endif + + // Now push the new interpreter frames. + // + __ bind(loop); + // Allocate a new frame, fill in the pc. + push_skeleton_frame(masm, deopt, + unroll_block_reg, + frame_sizes_reg, + number_of_frames_reg, + pcs_reg, + frame_size_reg, + pc_reg); + __ cmpdi(CCR0, number_of_frames_reg, 0); + __ bne(CCR0, loop); + + // Get the return address pointing into the frame manager. + __ ld(R0, 0, pcs_reg); + // Store it in the top interpreter frame. + __ std(R0, _abi(lr), R1_SP); + // Initialize frame_manager_lr of interpreter top frame. + __ std(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); +} +#endif + +void SharedRuntime::generate_deopt_blob() { + // Allocate space for the code + ResourceMark rm; + // Setup code generation tools + CodeBuffer buffer("deopt_blob", 2048, 1024); + InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); + Label exec_mode_initialized; + int frame_size_in_words; + OopMap* map = NULL; + OopMapSet *oop_maps = new OopMapSet(); + + // size of ABI112 plus spill slots for R3_RET and F1_RET. + const int frame_size_in_bytes = frame::abi_112_spill_size; + const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); + int first_frame_size_in_bytes = 0; // frame size of "unpack frame" for call to fetch_unroll_info. + + const Register exec_mode_reg = R21_tmp1; + + const address start = __ pc(); + +#ifdef COMPILER2 + // -------------------------------------------------------------------------- + // Prolog for non exception case! + + // We have been called from the deopt handler of the deoptee. + // + // deoptee: + // ... + // call X + // ... + // deopt_handler: call_deopt_stub + // cur. return pc --> ... + // + // So currently SR_LR points behind the call in the deopt handler. + // We adjust it such that it points to the start of the deopt handler. + // The return_pc has been stored in the frame of the deoptee and + // will replace the address of the deopt_handler in the call + // to Deoptimization::fetch_unroll_info below. + // We can't grab a free register here, because all registers may + // contain live values, so let the RegisterSaver do the adjustment + // of the return pc. + const int return_pc_adjustment_no_exception = -size_deopt_handler(); + + // Push the "unpack frame" + // Save everything in sight. + map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm, + &first_frame_size_in_bytes, + /*generate_oop_map=*/ true, + return_pc_adjustment_no_exception, + RegisterSaver::return_pc_is_lr); + assert(map != NULL, "OopMap must have been created"); + + __ li(exec_mode_reg, Deoptimization::Unpack_deopt); + // Save exec mode for unpack_frames. + __ b(exec_mode_initialized); + + // -------------------------------------------------------------------------- + // Prolog for exception case + + // An exception is pending. + // We have been called with a return (interpreter) or a jump (exception blob). + // + // - R3_ARG1: exception oop + // - R4_ARG2: exception pc + + int exception_offset = __ pc() - start; + + BLOCK_COMMENT("Prolog for exception case"); + + // The RegisterSaves doesn't need to adjust the return pc for this situation. + const int return_pc_adjustment_exception = 0; + + // Push the "unpack frame". + // Save everything in sight. + assert(R4 == R4_ARG2, "exception pc must be in r4"); + RegisterSaver::push_frame_abi112_and_save_live_registers(masm, + &first_frame_size_in_bytes, + /*generate_oop_map=*/ false, + return_pc_adjustment_exception, + RegisterSaver::return_pc_is_r4); + + // Deopt during an exception. Save exec mode for unpack_frames. + __ li(exec_mode_reg, Deoptimization::Unpack_exception); + + // Store exception oop and pc in thread (location known to GC). + // This is needed since the call to "fetch_unroll_info()" may safepoint. + __ std(R3_ARG1, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + __ std(R4_ARG2, in_bytes(JavaThread::exception_pc_offset()), R16_thread); + + // fall through + + // -------------------------------------------------------------------------- + __ BIND(exec_mode_initialized); + + { + const Register unroll_block_reg = R22_tmp2; + + // We need to set `last_Java_frame' because `fetch_unroll_info' will + // call `last_Java_frame()'. The value of the pc in the frame is not + // particularly important. It just needs to identify this blob. + __ set_last_Java_frame(R1_SP, noreg); + + // With EscapeAnalysis turned on, this call may safepoint! + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), R16_thread); + address calls_return_pc = __ last_calls_return_pc(); + // Set an oopmap for the call site that describes all our saved registers. + oop_maps->add_gc_map(calls_return_pc - start, map); + + __ reset_last_Java_frame(); + // Save the return value. + __ mr(unroll_block_reg, R3_RET); + + // Restore only the result registers that have been saved + // by save_volatile_registers(...). + RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes); + + // In excp_deopt_mode, restore and clear exception oop which we + // stored in the thread during exception entry above. The exception + // oop will be the return value of this stub. + Label skip_restore_excp; + __ cmpdi(CCR0, exec_mode_reg, Deoptimization::Unpack_exception); + __ bne(CCR0, skip_restore_excp); + __ ld(R3_RET, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + __ ld(R4_ARG2, in_bytes(JavaThread::exception_pc_offset()), R16_thread); + __ li(R0, 0); + __ std(R0, in_bytes(JavaThread::exception_pc_offset()), R16_thread); + __ std(R0, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + __ BIND(skip_restore_excp); + + // reload narrro_oop_base + if (UseCompressedOops && Universe::narrow_oop_base() != 0) { + __ load_const_optimized(R30, Universe::narrow_oop_base()); + } + + __ pop_frame(); + + // stack: (deoptee, optional i2c, caller of deoptee, ...). + + // pop the deoptee's frame + __ pop_frame(); + + // stack: (caller_of_deoptee, ...). + + // Loop through the `UnrollBlock' info and create interpreter frames. + push_skeleton_frames(masm, true/*deopt*/, + unroll_block_reg, + R23_tmp3, + R24_tmp4, + R25_tmp5, + R26_tmp6, + R27_tmp7); + + // stack: (skeletal interpreter frame, ..., optional skeletal + // interpreter frame, optional c2i, caller of deoptee, ...). + } + + // push an `unpack_frame' taking care of float / int return values. + __ push_frame(frame_size_in_bytes, R0/*tmp*/); + + // stack: (unpack frame, skeletal interpreter frame, ..., optional + // skeletal interpreter frame, optional c2i, caller of deoptee, + // ...). + + // Spill live volatile registers since we'll do a call. + __ std( R3_RET, _abi_112_spill(spill_ret), R1_SP); + __ stfd(F1_RET, _abi_112_spill(spill_fret), R1_SP); + + // Let the unpacker layout information in the skeletal frames just + // allocated. + __ get_PC_trash_LR(R3_RET); + __ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R3_RET); + // This is a call to a LEAF method, so no oop map is required. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), + R16_thread/*thread*/, exec_mode_reg/*exec_mode*/); + __ reset_last_Java_frame(); + + // Restore the volatiles saved above. + __ ld( R3_RET, _abi_112_spill(spill_ret), R1_SP); + __ lfd(F1_RET, _abi_112_spill(spill_fret), R1_SP); + + // Pop the unpack frame. + __ pop_frame(); + __ restore_LR_CR(R0); + + // stack: (top interpreter frame, ..., optional interpreter frame, + // optional c2i, caller of deoptee, ...). + + // Initialize R14_state. + __ ld(R14_state, 0, R1_SP); + __ addi(R14_state, R14_state, + -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + // Also inititialize R15_prev_state. + __ restore_prev_state(); + + // Return to the interpreter entry point. + __ blr(); + __ flush(); +#else // COMPILER2 + __ unimplemented("deopt blob needed only with compiler"); + int exception_offset = __ pc() - start; +#endif // COMPILER2 + + _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, 0, first_frame_size_in_bytes / wordSize); +} + +#ifdef COMPILER2 +void SharedRuntime::generate_uncommon_trap_blob() { + // Allocate space for the code. + ResourceMark rm; + // Setup code generation tools. + CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); + address start = __ pc(); + + Register unroll_block_reg = R21_tmp1; + Register klass_index_reg = R22_tmp2; + Register unc_trap_reg = R23_tmp3; + + OopMapSet* oop_maps = new OopMapSet(); + int frame_size_in_bytes = frame::abi_112_size; + OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); + + // stack: (deoptee, optional i2c, caller_of_deoptee, ...). + + // Push a dummy `unpack_frame' and call + // `Deoptimization::uncommon_trap' to pack the compiled frame into a + // vframe array and return the `UnrollBlock' information. + + // Save LR to compiled frame. + __ save_LR_CR(R11_scratch1); + + // Push an "uncommon_trap" frame. + __ push_frame_abi112(0, R11_scratch1); + + // stack: (unpack frame, deoptee, optional i2c, caller_of_deoptee, ...). + + // Set the `unpack_frame' as last_Java_frame. + // `Deoptimization::uncommon_trap' expects it and considers its + // sender frame as the deoptee frame. + // Remember the offset of the instruction whose address will be + // moved to R11_scratch1. + address gc_map_pc = __ get_PC_trash_LR(R11_scratch1); + + __ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1); + + __ mr(klass_index_reg, R3); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), + R16_thread, klass_index_reg); + + // Set an oopmap for the call site. + oop_maps->add_gc_map(gc_map_pc - start, map); + + __ reset_last_Java_frame(); + + // Pop the `unpack frame'. + __ pop_frame(); + + // stack: (deoptee, optional i2c, caller_of_deoptee, ...). + + // Save the return value. + __ mr(unroll_block_reg, R3_RET); + + // Pop the uncommon_trap frame. + __ pop_frame(); + + // stack: (caller_of_deoptee, ...). + + // Allocate new interpreter frame(s) and possibly a c2i adapter + // frame. + push_skeleton_frames(masm, false/*deopt*/, + unroll_block_reg, + R22_tmp2, + R23_tmp3, + R24_tmp4, + R25_tmp5, + R26_tmp6); + + // stack: (skeletal interpreter frame, ..., optional skeletal + // interpreter frame, optional c2i, caller of deoptee, ...). + + // Push a dummy `unpack_frame' taking care of float return values. + // Call `Deoptimization::unpack_frames' to layout information in the + // interpreter frames just created. + + // Push a simple "unpack frame" here. + __ push_frame_abi112(0, R11_scratch1); + + // stack: (unpack frame, skeletal interpreter frame, ..., optional + // skeletal interpreter frame, optional c2i, caller of deoptee, + // ...). + + // Set the "unpack_frame" as last_Java_frame. + __ get_PC_trash_LR(R11_scratch1); + __ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1); + + // Indicate it is the uncommon trap case. + __ li(unc_trap_reg, Deoptimization::Unpack_uncommon_trap); + // Let the unpacker layout information in the skeletal frames just + // allocated. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), + R16_thread, unc_trap_reg); + + __ reset_last_Java_frame(); + // Pop the `unpack frame'. + __ pop_frame(); + // Restore LR from top interpreter frame. + __ restore_LR_CR(R11_scratch1); + + // stack: (top interpreter frame, ..., optional interpreter frame, + // optional c2i, caller of deoptee, ...). + + // Initialize R14_state, ... + __ ld(R11_scratch1, 0, R1_SP); + __ addi(R14_state, R11_scratch1, + -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + // also initialize R15_prev_state. + __ restore_prev_state(); + // Return to the interpreter entry point. + __ blr(); + + masm->flush(); + + _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, frame_size_in_bytes/wordSize); +} +#endif // COMPILER2 + +// Generate a special Compile2Runtime blob that saves all registers, and setup oopmap. +SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_type) { + assert(StubRoutines::forward_exception_entry() != NULL, + "must be generated before"); + + ResourceMark rm; + OopMapSet *oop_maps = new OopMapSet(); + OopMap* map; + + // Allocate space for the code. Setup code generation tools. + CodeBuffer buffer("handler_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + address start = __ pc(); + int frame_size_in_bytes = 0; + + RegisterSaver::ReturnPCLocation return_pc_location; + bool cause_return = (poll_type == POLL_AT_RETURN); + if (cause_return) { + // Nothing to do here. The frame has already been popped in MachEpilogNode. + // Register LR already contains the return pc. + return_pc_location = RegisterSaver::return_pc_is_lr; + } else { + // Use thread()->saved_exception_pc() as return pc. + return_pc_location = RegisterSaver::return_pc_is_thread_saved_exception_pc; + } + + // Save registers, fpu state, and flags. + map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm, + &frame_size_in_bytes, + /*generate_oop_map=*/ true, + /*return_pc_adjustment=*/0, + return_pc_location); + + // The following is basically a call_VM. However, we need the precise + // address of the call in order to generate an oopmap. Hence, we do all the + // work outselves. + __ set_last_Java_frame(/*sp=*/R1_SP, /*pc=*/noreg); + + // The return address must always be correct so that the frame constructor + // never sees an invalid pc. + + // Do the call + __ call_VM_leaf(call_ptr, R16_thread); + address calls_return_pc = __ last_calls_return_pc(); + + // Set an oopmap for the call site. This oopmap will map all + // oop-registers and debug-info registers as callee-saved. This + // will allow deoptimization at this safepoint to find all possible + // debug-info recordings, as well as let GC find all oops. + oop_maps->add_gc_map(calls_return_pc - start, map); + + Label noException; + + // Clear the last Java frame. + __ reset_last_Java_frame(); + + BLOCK_COMMENT(" Check pending exception."); + const Register pending_exception = R0; + __ ld(pending_exception, thread_(pending_exception)); + __ cmpdi(CCR0, pending_exception, 0); + __ beq(CCR0, noException); + + // Exception pending + RegisterSaver::restore_live_registers_and_pop_frame(masm, + frame_size_in_bytes, + /*restore_ctr=*/true); + + + BLOCK_COMMENT(" Jump to forward_exception_entry."); + // Jump to forward_exception_entry, with the issuing PC in LR + // so it looks like the original nmethod called forward_exception_entry. + __ b64_patchable(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + + // No exception case. + __ BIND(noException); + + + // Normal exit, restore registers and exit. + RegisterSaver::restore_live_registers_and_pop_frame(masm, + frame_size_in_bytes, + /*restore_ctr=*/true); + + __ blr(); + + // Make sure all code is generated + masm->flush(); + + // Fill-out other meta info + // CodeBlob frame size is in words. + return SafepointBlob::create(&buffer, oop_maps, frame_size_in_bytes / wordSize); +} + +// generate_resolve_blob - call resolution (static/virtual/opt-virtual/ic-miss) +// +// Generate a stub that calls into the vm to find out the proper destination +// of a java call. All the argument registers are live at this point +// but since this is generic code we don't know what they are and the caller +// must do any gc of the args. +// +RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const char* name) { + + // allocate space for the code + ResourceMark rm; + + CodeBuffer buffer(name, 1000, 512); + MacroAssembler* masm = new MacroAssembler(&buffer); + + int frame_size_in_bytes; + + OopMapSet *oop_maps = new OopMapSet(); + OopMap* map = NULL; + + address start = __ pc(); + + map = RegisterSaver::push_frame_abi112_and_save_live_registers(masm, + &frame_size_in_bytes, + /*generate_oop_map*/ true, + /*return_pc_adjustment*/ 0, + RegisterSaver::return_pc_is_lr); + + // Use noreg as last_Java_pc, the return pc will be reconstructed + // from the physical frame. + __ set_last_Java_frame(/*sp*/R1_SP, noreg); + + int frame_complete = __ offset(); + + // Pass R19_method as 2nd (optional) argument, used by + // counter_overflow_stub. + __ call_VM_leaf(destination, R16_thread, R19_method); + address calls_return_pc = __ last_calls_return_pc(); + // Set an oopmap for the call site. + // We need this not only for callee-saved registers, but also for volatile + // registers that the compiler might be keeping live across a safepoint. + // Create the oopmap for the call's return pc. + oop_maps->add_gc_map(calls_return_pc - start, map); + + // R3_RET contains the address we are going to jump to assuming no exception got installed. + + // clear last_Java_sp + __ reset_last_Java_frame(); + + // Check for pending exceptions. + BLOCK_COMMENT("Check for pending exceptions."); + Label pending; + __ ld(R11_scratch1, thread_(pending_exception)); + __ cmpdi(CCR0, R11_scratch1, 0); + __ bne(CCR0, pending); + + __ mtctr(R3_RET); // Ctr will not be touched by restore_live_registers_and_pop_frame. + + RegisterSaver::restore_live_registers_and_pop_frame(masm, frame_size_in_bytes, /*restore_ctr*/ false); + + // Get the returned methodOop. + __ get_vm_result_2(R19_method); + + __ bctr(); + + + // Pending exception after the safepoint. + __ BIND(pending); + + RegisterSaver::restore_live_registers_and_pop_frame(masm, frame_size_in_bytes, /*restore_ctr*/ true); + + // exception pending => remove activation and forward to exception handler + + __ li(R11_scratch1, 0); + __ ld(R3_ARG1, thread_(pending_exception)); + __ std(R11_scratch1, in_bytes(JavaThread::vm_result_offset()), R16_thread); + __ b64_patchable(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + + // ------------- + // Make sure all code is generated. + masm->flush(); + + // return the blob + // frame_size_words or bytes?? + return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_bytes/wordSize, + oop_maps, true); +} diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp new file mode 100644 index 00000000000..d5f8be7c4bd --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -0,0 +1,2057 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "nativeInst_ppc.hpp" +#include "oops/instanceOop.hpp" +#include "oops/method.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/top.hpp" +#ifdef TARGET_OS_FAMILY_aix +# include "thread_aix.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_linux +# include "thread_linux.inline.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +class StubGenerator: public StubCodeGenerator { + private: + + // Call stubs are used to call Java from C + // + // Arguments: + // + // R3 - call wrapper address : address + // R4 - result : intptr_t* + // R5 - result type : BasicType + // R6 - method : Method + // R7 - frame mgr entry point : address + // R8 - parameter block : intptr_t* + // R9 - parameter count in words : int + // R10 - thread : Thread* + // + address generate_call_stub(address& return_address) { + // Setup a new c frame, copy java arguments, call frame manager or + // native_entry, and process result. + + StubCodeMark mark(this, "StubRoutines", "call_stub"); + + address start = __ emit_fd(); + + // some sanity checks + assert((sizeof(frame::abi_48) % 16) == 0, "unaligned"); + assert((sizeof(frame::abi_112) % 16) == 0, "unaligned"); + assert((sizeof(frame::spill_nonvolatiles) % 16) == 0, "unaligned"); + assert((sizeof(frame::parent_ijava_frame_abi) % 16) == 0, "unaligned"); + assert((sizeof(frame::entry_frame_locals) % 16) == 0, "unaligned"); + + Register r_arg_call_wrapper_addr = R3; + Register r_arg_result_addr = R4; + Register r_arg_result_type = R5; + Register r_arg_method = R6; + Register r_arg_entry = R7; + Register r_arg_thread = R10; + + Register r_temp = R24; + Register r_top_of_arguments_addr = R25; + Register r_entryframe_fp = R26; + + { + // Stack on entry to call_stub: + // + // F1 [C_FRAME] + // ... + + Register r_arg_argument_addr = R8; + Register r_arg_argument_count = R9; + Register r_frame_alignment_in_bytes = R27; + Register r_argument_addr = R28; + Register r_argumentcopy_addr = R29; + Register r_argument_size_in_bytes = R30; + Register r_frame_size = R23; + + Label arguments_copied; + + // Save LR/CR to caller's C_FRAME. + __ save_LR_CR(R0); + + // Zero extend arg_argument_count. + __ clrldi(r_arg_argument_count, r_arg_argument_count, 32); + + // Save non-volatiles GPRs to ENTRY_FRAME (not yet pushed, but it's safe). + __ save_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); + + // Keep copy of our frame pointer (caller's SP). + __ mr(r_entryframe_fp, R1_SP); + + BLOCK_COMMENT("Push ENTRY_FRAME including arguments"); + // Push ENTRY_FRAME including arguments: + // + // F0 [TOP_IJAVA_FRAME_ABI] + // alignment (optional) + // [outgoing Java arguments] + // [ENTRY_FRAME_LOCALS] + // F1 [C_FRAME] + // ... + + // calculate frame size + + // unaligned size of arguments + __ sldi(r_argument_size_in_bytes, + r_arg_argument_count, Interpreter::logStackElementSize); + // arguments alignment (max 1 slot) + // FIXME: use round_to() here + __ andi_(r_frame_alignment_in_bytes, r_arg_argument_count, 1); + __ sldi(r_frame_alignment_in_bytes, + r_frame_alignment_in_bytes, Interpreter::logStackElementSize); + + // size = unaligned size of arguments + top abi's size + __ addi(r_frame_size, r_argument_size_in_bytes, + frame::top_ijava_frame_abi_size); + // size += arguments alignment + __ add(r_frame_size, + r_frame_size, r_frame_alignment_in_bytes); + // size += size of call_stub locals + __ addi(r_frame_size, + r_frame_size, frame::entry_frame_locals_size); + + // push ENTRY_FRAME + __ push_frame(r_frame_size, r_temp); + + // initialize call_stub locals (step 1) + __ std(r_arg_call_wrapper_addr, + _entry_frame_locals_neg(call_wrapper_address), r_entryframe_fp); + __ std(r_arg_result_addr, + _entry_frame_locals_neg(result_address), r_entryframe_fp); + __ std(r_arg_result_type, + _entry_frame_locals_neg(result_type), r_entryframe_fp); + // we will save arguments_tos_address later + + + BLOCK_COMMENT("Copy Java arguments"); + // copy Java arguments + + // Calculate top_of_arguments_addr which will be R17_tos (not prepushed) later. + // FIXME: why not simply use SP+frame::top_ijava_frame_size? + __ addi(r_top_of_arguments_addr, + R1_SP, frame::top_ijava_frame_abi_size); + __ add(r_top_of_arguments_addr, + r_top_of_arguments_addr, r_frame_alignment_in_bytes); + + // any arguments to copy? + __ cmpdi(CCR0, r_arg_argument_count, 0); + __ beq(CCR0, arguments_copied); + + // prepare loop and copy arguments in reverse order + { + // init CTR with arg_argument_count + __ mtctr(r_arg_argument_count); + + // let r_argumentcopy_addr point to last outgoing Java arguments P + __ mr(r_argumentcopy_addr, r_top_of_arguments_addr); + + // let r_argument_addr point to last incoming java argument + __ add(r_argument_addr, + r_arg_argument_addr, r_argument_size_in_bytes); + __ addi(r_argument_addr, r_argument_addr, -BytesPerWord); + + // now loop while CTR > 0 and copy arguments + { + Label next_argument; + __ bind(next_argument); + + __ ld(r_temp, 0, r_argument_addr); + // argument_addr--; + __ addi(r_argument_addr, r_argument_addr, -BytesPerWord); + __ std(r_temp, 0, r_argumentcopy_addr); + // argumentcopy_addr++; + __ addi(r_argumentcopy_addr, r_argumentcopy_addr, BytesPerWord); + + __ bdnz(next_argument); + } + } + + // Arguments copied, continue. + __ bind(arguments_copied); + } + + { + BLOCK_COMMENT("Call frame manager or native entry."); + // Call frame manager or native entry. + Register r_new_arg_entry = R14_state; + assert_different_registers(r_new_arg_entry, r_top_of_arguments_addr, + r_arg_method, r_arg_thread); + + __ mr(r_new_arg_entry, r_arg_entry); + + // Register state on entry to frame manager / native entry: + // + // R17_tos - intptr_t* sender tos (prepushed) Lesp = (SP) + copied_arguments_offset - 8 + // R19_method - Method + // R16_thread - JavaThread* + + // R17_tos must point to last argument - element_size. + __ addi(R17_tos, r_top_of_arguments_addr, -Interpreter::stackElementSize); + + // initialize call_stub locals (step 2) + // now save R17_tos as arguments_tos_address + __ std(R17_tos, _entry_frame_locals_neg(arguments_tos_address), r_entryframe_fp); + + // load argument registers for call + __ mr(R19_method, r_arg_method); + __ mr(R16_thread, r_arg_thread); + assert(R17_tos != r_arg_method, "trashed r_arg_method"); + assert(R17_tos != r_arg_thread && R19_method != r_arg_thread, "trashed r_arg_thread"); + + // Set R15_prev_state to 0 for simplifying checks in callee. + __ li(R15_prev_state, 0); + + // Stack on entry to frame manager / native entry: + // + // F0 [TOP_IJAVA_FRAME_ABI] + // alignment (optional) + // [outgoing Java arguments] + // [ENTRY_FRAME_LOCALS] + // F1 [C_FRAME] + // ... + // + + // global toc register + __ load_const(R29, MacroAssembler::global_toc(), R11_scratch1); + + // Load narrow oop base. + __ reinit_heapbase(R30, R11_scratch1); + + // Remember the senderSP so we interpreter can pop c2i arguments off of the stack + // when called via a c2i. + + // Pass initial_caller_sp to framemanager. + __ mr(R21_tmp1, R1_SP); + + // Do a light-weight C-call here, r_new_arg_entry holds the address + // of the interpreter entry point (frame manager or native entry) + // and save runtime-value of LR in return_address. + assert(r_new_arg_entry != R17_tos && r_new_arg_entry != R19_method && r_new_arg_entry != R16_thread, + "trashed r_new_arg_entry"); + return_address = __ call_stub(r_new_arg_entry); + } + + { + BLOCK_COMMENT("Returned from frame manager or native entry."); + // Returned from frame manager or native entry. + // Now pop frame, process result, and return to caller. + + // Stack on exit from frame manager / native entry: + // + // F0 [ABI] + // ... + // [ENTRY_FRAME_LOCALS] + // F1 [C_FRAME] + // ... + // + // Just pop the topmost frame ... + // + + Label ret_is_object; + Label ret_is_long; + Label ret_is_float; + Label ret_is_double; + + Register r_entryframe_fp = R30; + Register r_lr = R7_ARG5; + Register r_cr = R8_ARG6; + + // Reload some volatile registers which we've spilled before the call + // to frame manager / native entry. + // Access all locals via frame pointer, because we know nothing about + // the topmost frame's size. + __ ld(r_entryframe_fp, _abi(callers_sp), R1_SP); + assert_different_registers(r_entryframe_fp, R3_RET, r_arg_result_addr, r_arg_result_type, r_cr, r_lr); + __ ld(r_arg_result_addr, + _entry_frame_locals_neg(result_address), r_entryframe_fp); + __ ld(r_arg_result_type, + _entry_frame_locals_neg(result_type), r_entryframe_fp); + __ ld(r_cr, _abi(cr), r_entryframe_fp); + __ ld(r_lr, _abi(lr), r_entryframe_fp); + + // pop frame and restore non-volatiles, LR and CR + __ mr(R1_SP, r_entryframe_fp); + __ mtcr(r_cr); + __ mtlr(r_lr); + + // Store result depending on type. Everything that is not + // T_OBJECT, T_LONG, T_FLOAT, or T_DOUBLE is treated as T_INT. + __ cmpwi(CCR0, r_arg_result_type, T_OBJECT); + __ cmpwi(CCR1, r_arg_result_type, T_LONG); + __ cmpwi(CCR5, r_arg_result_type, T_FLOAT); + __ cmpwi(CCR6, r_arg_result_type, T_DOUBLE); + + // restore non-volatile registers + __ restore_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); + + + // Stack on exit from call_stub: + // + // 0 [C_FRAME] + // ... + // + // no call_stub frames left. + + // All non-volatiles have been restored at this point!! + assert(R3_RET == R3, "R3_RET should be R3"); + + __ beq(CCR0, ret_is_object); + __ beq(CCR1, ret_is_long); + __ beq(CCR5, ret_is_float); + __ beq(CCR6, ret_is_double); + + // default: + __ stw(R3_RET, 0, r_arg_result_addr); + __ blr(); // return to caller + + // case T_OBJECT: + __ bind(ret_is_object); + __ std(R3_RET, 0, r_arg_result_addr); + __ blr(); // return to caller + + // case T_LONG: + __ bind(ret_is_long); + __ std(R3_RET, 0, r_arg_result_addr); + __ blr(); // return to caller + + // case T_FLOAT: + __ bind(ret_is_float); + __ stfs(F1_RET, 0, r_arg_result_addr); + __ blr(); // return to caller + + // case T_DOUBLE: + __ bind(ret_is_double); + __ stfd(F1_RET, 0, r_arg_result_addr); + __ blr(); // return to caller + } + + return start; + } + + // Return point for a Java call if there's an exception thrown in + // Java code. The exception is caught and transformed into a + // pending exception stored in JavaThread that can be tested from + // within the VM. + // + address generate_catch_exception() { + StubCodeMark mark(this, "StubRoutines", "catch_exception"); + + address start = __ pc(); + + // Registers alive + // + // R16_thread + // R3_ARG1 - address of pending exception + // R4_ARG2 - return address in call stub + + const Register exception_file = R21_tmp1; + const Register exception_line = R22_tmp2; + + __ load_const(exception_file, (void*)__FILE__); + __ load_const(exception_line, (void*)__LINE__); + + __ std(R3_ARG1, thread_(pending_exception)); + // store into `char *' + __ std(exception_file, thread_(exception_file)); + // store into `int' + __ stw(exception_line, thread_(exception_line)); + + // complete return to VM + assert(StubRoutines::_call_stub_return_address != NULL, "must have been generated before"); + + __ mtlr(R4_ARG2); + // continue in call stub + __ blr(); + + return start; + } + + // Continuation point for runtime calls returning with a pending + // exception. The pending exception check happened in the runtime + // or native call stub. The pending exception in Thread is + // converted into a Java-level exception. + // + address generate_forward_exception() { + StubCodeMark mark(this, "StubRoutines", "forward_exception"); + address start = __ pc(); + +#if !defined(PRODUCT) + if (VerifyOops) { + // Get pending exception oop. + __ ld(R3_ARG1, + in_bytes(Thread::pending_exception_offset()), + R16_thread); + // Make sure that this code is only executed if there is a pending exception. + { + Label L; + __ cmpdi(CCR0, R3_ARG1, 0); + __ bne(CCR0, L); + __ stop("StubRoutines::forward exception: no pending exception (1)"); + __ bind(L); + } + __ verify_oop(R3_ARG1, "StubRoutines::forward exception: not an oop"); + } +#endif + + // Save LR/CR and copy exception pc (LR) into R4_ARG2. + __ save_LR_CR(R4_ARG2); + __ push_frame_abi112(0, R0); + // Find exception handler. + __ call_VM_leaf(CAST_FROM_FN_PTR(address, + SharedRuntime::exception_handler_for_return_address), + R16_thread, + R4_ARG2); + // Copy handler's address. + __ mtctr(R3_RET); + __ pop_frame(); + __ restore_LR_CR(R0); + + // Set up the arguments for the exception handler: + // - R3_ARG1: exception oop + // - R4_ARG2: exception pc. + + // Load pending exception oop. + __ ld(R3_ARG1, + in_bytes(Thread::pending_exception_offset()), + R16_thread); + + // The exception pc is the return address in the caller. + // Must load it into R4_ARG2. + __ mflr(R4_ARG2); + +#ifdef ASSERT + // Make sure exception is set. + { + Label L; + __ cmpdi(CCR0, R3_ARG1, 0); + __ bne(CCR0, L); + __ stop("StubRoutines::forward exception: no pending exception (2)"); + __ bind(L); + } +#endif + + // Clear the pending exception. + __ li(R0, 0); + __ std(R0, + in_bytes(Thread::pending_exception_offset()), + R16_thread); + // Jump to exception handler. + __ bctr(); + + return start; + } + +#undef __ +#define __ masm-> + // Continuation point for throwing of implicit exceptions that are + // not handled in the current activation. Fabricates an exception + // oop and initiates normal exception dispatching in this + // frame. Only callee-saved registers are preserved (through the + // normal register window / RegisterMap handling). If the compiler + // needs all registers to be preserved between the fault point and + // the exception handler then it must assume responsibility for that + // in AbstractCompiler::continuation_for_implicit_null_exception or + // continuation_for_implicit_division_by_zero_exception. All other + // implicit exceptions (e.g., NullPointerException or + // AbstractMethodError on entry) are either at call sites or + // otherwise assume that stack unwinding will be initiated, so + // caller saved registers were assumed volatile in the compiler. + // + // Note that we generate only this stub into a RuntimeStub, because + // it needs to be properly traversed and ignored during GC, so we + // change the meaning of the "__" macro within this method. + // + // Note: the routine set_pc_not_at_call_for_caller in + // SharedRuntime.cpp requires that this code be generated into a + // RuntimeStub. + address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc, + Register arg1 = noreg, Register arg2 = noreg) { + CodeBuffer code(name, 1024 DEBUG_ONLY(+ 512), 0); + MacroAssembler* masm = new MacroAssembler(&code); + + OopMapSet* oop_maps = new OopMapSet(); + int frame_size_in_bytes = frame::abi_112_size; + OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); + + StubCodeMark mark(this, "StubRoutines", "throw_exception"); + + address start = __ pc(); + + __ save_LR_CR(R11_scratch1); + + // Push a frame. + __ push_frame_abi112(0, R11_scratch1); + + address frame_complete_pc = __ pc(); + + if (restore_saved_exception_pc) { + __ unimplemented("StubGenerator::throw_exception with restore_saved_exception_pc", 74); + } + + // Note that we always have a runtime stub frame on the top of + // stack by this point. Remember the offset of the instruction + // whose address will be moved to R11_scratch1. + address gc_map_pc = __ get_PC_trash_LR(R11_scratch1); + + __ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1); + + __ mr(R3_ARG1, R16_thread); + if (arg1 != noreg) { + __ mr(R4_ARG2, arg1); + } + if (arg2 != noreg) { + __ mr(R5_ARG3, arg2); + } + __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, runtime_entry), + relocInfo::none); + + // Set an oopmap for the call site. + oop_maps->add_gc_map((int)(gc_map_pc - start), map); + + __ reset_last_Java_frame(); + +#ifdef ASSERT + // Make sure that this code is only executed if there is a pending + // exception. + { + Label L; + __ ld(R0, + in_bytes(Thread::pending_exception_offset()), + R16_thread); + __ cmpdi(CCR0, R0, 0); + __ bne(CCR0, L); + __ stop("StubRoutines::throw_exception: no pending exception"); + __ bind(L); + } +#endif + + // Pop frame. + __ pop_frame(); + + __ restore_LR_CR(R11_scratch1); + + __ load_const(R11_scratch1, StubRoutines::forward_exception_entry()); + __ mtctr(R11_scratch1); + __ bctr(); + + // Create runtime stub with OopMap. + RuntimeStub* stub = + RuntimeStub::new_runtime_stub(name, &code, + /*frame_complete=*/ (int)(frame_complete_pc - start), + frame_size_in_bytes/wordSize, + oop_maps, + false); + return stub->entry_point(); + } +#undef __ +#define __ _masm-> + + // Generate G1 pre-write barrier for array. + // + // Input: + // from - register containing src address (only needed for spilling) + // to - register containing starting address + // count - register containing element count + // tmp - scratch register + // + // Kills: + // nothing + // + void gen_write_ref_array_pre_barrier(Register from, Register to, Register count, bool dest_uninitialized, Register Rtmp1) { + BarrierSet* const bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: + // With G1, don't generate the call if we statically know that the target in uninitialized + if (!dest_uninitialized) { + const int spill_slots = 4 * wordSize; + const int frame_size = frame::abi_112_size + spill_slots; + + __ save_LR_CR(R0); + __ push_frame_abi112(spill_slots, R0); + __ std(from, frame_size - 1 * wordSize, R1_SP); + __ std(to, frame_size - 2 * wordSize, R1_SP); + __ std(count, frame_size - 3 * wordSize, R1_SP); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), to, count); + + __ ld(from, frame_size - 1 * wordSize, R1_SP); + __ ld(to, frame_size - 2 * wordSize, R1_SP); + __ ld(count, frame_size - 3 * wordSize, R1_SP); + __ pop_frame(); + __ restore_LR_CR(R0); + } + break; + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + case BarrierSet::ModRef: + break; + default: + ShouldNotReachHere(); + } + } + + // Generate CMS/G1 post-write barrier for array. + // + // Input: + // addr - register containing starting address + // count - register containing element count + // tmp - scratch register + // + // The input registers and R0 are overwritten. + // + void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp) { + BarrierSet* const bs = Universe::heap()->barrier_set(); + + switch (bs->kind()) { + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: + { + __ save_LR_CR(R0); + // We need this frame only that the callee can spill LR/CR. + __ push_frame_abi112(0, R0); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); + + __ pop_frame(); + __ restore_LR_CR(R0); + } + break; + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + { + Label Lskip_loop, Lstore_loop; + if (UseConcMarkSweepGC) { + // TODO PPC port: contribute optimization / requires shared changes + __ release(); + } + + CardTableModRefBS* const ct = (CardTableModRefBS*)bs; + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); + assert_different_registers(addr, count, tmp); + + __ sldi(count, count, LogBytesPerHeapOop); + __ addi(count, count, -BytesPerHeapOop); + __ add(count, addr, count); + // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.) + __ srdi(addr, addr, CardTableModRefBS::card_shift); + __ srdi(count, count, CardTableModRefBS::card_shift); + __ subf(count, addr, count); + assert_different_registers(R0, addr, count, tmp); + __ load_const(tmp, (address)ct->byte_map_base); + __ addic_(count, count, 1); + __ beq(CCR0, Lskip_loop); + __ li(R0, 0); + __ mtctr(count); + // Byte store loop + __ bind(Lstore_loop); + __ stbx(R0, tmp, addr); + __ addi(addr, addr, 1); + __ bdnz(Lstore_loop); + __ bind(Lskip_loop); + } + break; + case BarrierSet::ModRef: + break; + default: + ShouldNotReachHere(); + } + } + + // Support for void zero_words_aligned8(HeapWord* to, size_t count) + // + // Arguments: + // to: + // count: + // + // Destroys: + // + address generate_zero_words_aligned8() { + StubCodeMark mark(this, "StubRoutines", "zero_words_aligned8"); + + // Implemented as in ClearArray. + address start = __ emit_fd(); + + Register base_ptr_reg = R3_ARG1; // tohw (needs to be 8b aligned) + Register cnt_dwords_reg = R4_ARG2; // count (in dwords) + Register tmp1_reg = R5_ARG3; + Register tmp2_reg = R6_ARG4; + Register zero_reg = R7_ARG5; + + // Procedure for large arrays (uses data cache block zero instruction). + Label dwloop, fast, fastloop, restloop, lastdword, done; + int cl_size=VM_Version::get_cache_line_size(), cl_dwords=cl_size>>3, cl_dwordaddr_bits=exact_log2(cl_dwords); + int min_dcbz=2; // Needs to be positive, apply dcbz only to at least min_dcbz cache lines. + + // Clear up to 128byte boundary if long enough, dword_cnt=(16-(base>>3))%16. + __ dcbtst(base_ptr_reg); // Indicate write access to first cache line ... + __ andi(tmp2_reg, cnt_dwords_reg, 1); // to check if number of dwords is even. + __ srdi_(tmp1_reg, cnt_dwords_reg, 1); // number of double dwords + __ load_const_optimized(zero_reg, 0L); // Use as zero register. + + __ cmpdi(CCR1, tmp2_reg, 0); // cnt_dwords even? + __ beq(CCR0, lastdword); // size <= 1 + __ mtctr(tmp1_reg); // Speculatively preload counter for rest loop (>0). + __ cmpdi(CCR0, cnt_dwords_reg, (min_dcbz+1)*cl_dwords-1); // Big enough to ensure >=min_dcbz cache lines are included? + __ neg(tmp1_reg, base_ptr_reg); // bit 0..58: bogus, bit 57..60: (16-(base>>3))%16, bit 61..63: 000 + + __ blt(CCR0, restloop); // Too small. (<31=(2*cl_dwords)-1 is sufficient, but bigger performs better.) + __ rldicl_(tmp1_reg, tmp1_reg, 64-3, 64-cl_dwordaddr_bits); // Extract number of dwords to 128byte boundary=(16-(base>>3))%16. + + __ beq(CCR0, fast); // already 128byte aligned + __ mtctr(tmp1_reg); // Set ctr to hit 128byte boundary (00 since size>=256-8) + + // Clear in first cache line dword-by-dword if not already 128byte aligned. + __ bind(dwloop); + __ std(zero_reg, 0, base_ptr_reg); // Clear 8byte aligned block. + __ addi(base_ptr_reg, base_ptr_reg, 8); + __ bdnz(dwloop); + + // clear 128byte blocks + __ bind(fast); + __ srdi(tmp1_reg, cnt_dwords_reg, cl_dwordaddr_bits); // loop count for 128byte loop (>0 since size>=256-8) + __ andi(tmp2_reg, cnt_dwords_reg, 1); // to check if rest even + + __ mtctr(tmp1_reg); // load counter + __ cmpdi(CCR1, tmp2_reg, 0); // rest even? + __ rldicl_(tmp1_reg, cnt_dwords_reg, 63, 65-cl_dwordaddr_bits); // rest in double dwords + + __ bind(fastloop); + __ dcbz(base_ptr_reg); // Clear 128byte aligned block. + __ addi(base_ptr_reg, base_ptr_reg, cl_size); + __ bdnz(fastloop); + + //__ dcbtst(base_ptr_reg); // Indicate write access to last cache line. + __ beq(CCR0, lastdword); // rest<=1 + __ mtctr(tmp1_reg); // load counter + + // Clear rest. + __ bind(restloop); + __ std(zero_reg, 0, base_ptr_reg); // Clear 8byte aligned block. + __ std(zero_reg, 8, base_ptr_reg); // Clear 8byte aligned block. + __ addi(base_ptr_reg, base_ptr_reg, 16); + __ bdnz(restloop); + + __ bind(lastdword); + __ beq(CCR1, done); + __ std(zero_reg, 0, base_ptr_reg); + __ bind(done); + __ blr(); // return + + return start; + } + + // The following routine generates a subroutine to throw an asynchronous + // UnknownError when an unsafe access gets a fault that could not be + // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.) + // + address generate_handler_for_unsafe_access() { + StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access"); + address start = __ emit_fd(); + __ unimplemented("StubRoutines::handler_for_unsafe_access", 93); + return start; + } + +#if !defined(PRODUCT) + // Wrapper which calls oopDesc::is_oop_or_null() + // Only called by MacroAssembler::verify_oop + static void verify_oop_helper(const char* message, oop o) { + if (!o->is_oop_or_null()) { + fatal(message); + } + ++ StubRoutines::_verify_oop_count; + } +#endif + + // Return address of code to be called from code generated by + // MacroAssembler::verify_oop. + // + // Don't generate, rather use C++ code. + address generate_verify_oop() { + StubCodeMark mark(this, "StubRoutines", "verify_oop"); + + // this is actually a `FunctionDescriptor*'. + address start = 0; + +#if !defined(PRODUCT) + start = CAST_FROM_FN_PTR(address, verify_oop_helper); +#endif + + return start; + } + + // Fairer handling of safepoints for native methods. + // + // Generate code which reads from the polling page. This special handling is needed as the + // linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults in 64bit mode + // (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6), especially when we try + // to read from the safepoint polling page. + address generate_load_from_poll() { + StubCodeMark mark(this, "StubRoutines", "generate_load_from_poll"); + address start = __ emit_fd(); + __ unimplemented("StubRoutines::verify_oop", 95); // TODO PPC port + return start; + } + + // -XX:+OptimizeFill : convert fill/copy loops into intrinsic + // + // The code is implemented(ported from sparc) as we believe it benefits JVM98, however + // tracing(-XX:+TraceOptimizeFill) shows the intrinsic replacement doesn't happen at all! + // + // Source code in function is_range_check_if() shows OptimizeFill relaxed the condition + // for turning on loop predication optimization, and hence the behavior of "array range check" + // and "loop invariant check" could be influenced, which potentially boosted JVM98. + // + // We leave the code here and see if Oracle has updates in later releases(later than HS20). + // + // Generate stub for disjoint short fill. If "aligned" is true, the + // "to" address is assumed to be heapword aligned. + // + // Arguments for generated stub: + // to: R3_ARG1 + // value: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_fill(BasicType t, bool aligned, const char* name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + const Register to = R3_ARG1; // source array address + const Register value = R4_ARG2; // fill value + const Register count = R5_ARG3; // elements count + const Register temp = R6_ARG4; // temp register + + //assert_clean_int(count, O3); // Make sure 'count' is clean int. + + Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; + Label L_fill_2_bytes, L_fill_4_bytes, L_fill_elements, L_fill_32_bytes; + + int shift = -1; + switch (t) { + case T_BYTE: + shift = 2; + // clone bytes (zero extend not needed because store instructions below ignore high order bytes) + __ rldimi(value, value, 8, 48); // 8 bit -> 16 bit + __ cmpdi(CCR0, count, 2< 32 bit + break; + case T_SHORT: + shift = 1; + // clone bytes (zero extend not needed because store instructions below ignore high order bytes) + __ rldimi(value, value, 16, 32); // 16 bit -> 32 bit + __ cmpdi(CCR0, count, 2<long as above + __ rldimi(value, value, 32, 0); // 32 bit -> 64 bit + + Label L_check_fill_8_bytes; + // Fill 32-byte chunks + __ subf_(count, temp, count); + __ blt(CCR0, L_check_fill_8_bytes); + + Label L_fill_32_bytes_loop; + __ align(32); + __ bind(L_fill_32_bytes_loop); + + __ std(value, 0, to); + __ std(value, 8, to); + __ subf_(count, temp, count); // update count + __ std(value, 16, to); + __ std(value, 24, to); + + __ addi(to, to, 32); + __ bge(CCR0, L_fill_32_bytes_loop); + + __ bind(L_check_fill_8_bytes); + __ add_(count, temp, count); + __ beq(CCR0, L_exit); + __ addic_(count, count, -(2 << shift)); + __ blt(CCR0, L_fill_4_bytes); + + // + // Length is too short, just fill 8 bytes at a time. + // + Label L_fill_8_bytes_loop; + __ bind(L_fill_8_bytes_loop); + __ std(value, 0, to); + __ addic_(count, count, -(2 << shift)); + __ addi(to, to, 8); + __ bge(CCR0, L_fill_8_bytes_loop); + + // fill trailing 4 bytes + __ bind(L_fill_4_bytes); + __ andi_(temp, count, 1< to or from is aligned -> copy 8 + + // copy a 2-element word if necessary to align to 8 bytes + __ andi_(R0, R3_ARG1, 7); + __ beq(CCR0, l_7); + + __ lwzx(tmp2, R3_ARG1, tmp3); + __ addi(R5_ARG3, R5_ARG3, -4); + __ stwx(tmp2, R4_ARG2, tmp3); + { // FasterArrayCopy + __ addi(R3_ARG1, R3_ARG1, 4); + __ addi(R4_ARG2, R4_ARG2, 4); + } + __ bind(l_7); + + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 31); + __ ble(CCR0, l_6); // copy 2 at a time if less than 32 elements remain + + __ srdi(tmp1, R5_ARG3, 5); + __ andi_(R5_ARG3, R5_ARG3, 31); + __ mtctr(tmp1); + + __ bind(l_8); + // Use unrolled version for mass copying (copy 32 elements a time) + // Load feeding store gets zero latency on Power6, however not on Power5. + // Therefore, the following sequence is made for the good of both. + __ ld(tmp1, 0, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp4, 24, R3_ARG1); + __ std(tmp1, 0, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp4, 24, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, 32); + __ addi(R4_ARG2, R4_ARG2, 32); + __ bdnz(l_8); + } + + __ bind(l_6); + + // copy 4 elements at a time + __ cmpwi(CCR0, R5_ARG3, 4); + __ blt(CCR0, l_1); + __ srdi(tmp1, R5_ARG3, 2); + __ mtctr(tmp1); // is > 0 + __ andi_(R5_ARG3, R5_ARG3, 3); + + { // FasterArrayCopy + __ addi(R3_ARG1, R3_ARG1, -4); + __ addi(R4_ARG2, R4_ARG2, -4); + __ bind(l_3); + __ lwzu(tmp2, 4, R3_ARG1); + __ stwu(tmp2, 4, R4_ARG2); + __ bdnz(l_3); + __ addi(R3_ARG1, R3_ARG1, 4); + __ addi(R4_ARG2, R4_ARG2, 4); + } + + // do single element copy + __ bind(l_1); + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_4); + + { // FasterArrayCopy + __ mtctr(R5_ARG3); + __ addi(R3_ARG1, R3_ARG1, -1); + __ addi(R4_ARG2, R4_ARG2, -1); + + __ bind(l_5); + __ lbzu(tmp2, 1, R3_ARG1); + __ stbu(tmp2, 1, R4_ARG2); + __ bdnz(l_5); + } + + __ bind(l_4); + __ blr(); + + return start; + } + + // Generate stub for conjoint byte copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_conjoint_byte_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + + address nooverlap_target = aligned ? + ((FunctionDescriptor*)StubRoutines::arrayof_jbyte_disjoint_arraycopy())->entry() : + ((FunctionDescriptor*)StubRoutines::jbyte_disjoint_arraycopy())->entry(); + + array_overlap_test(nooverlap_target, 0); + // Do reverse copy. We assume the case of actual overlap is rare enough + // that we don't have to optimize it. + Label l_1, l_2; + + __ b(l_2); + __ bind(l_1); + __ stbx(tmp1, R4_ARG2, R5_ARG3); + __ bind(l_2); + __ addic_(R5_ARG3, R5_ARG3, -1); + __ lbzx(tmp1, R3_ARG1, R5_ARG3); + __ bge(CCR0, l_1); + + __ blr(); + + return start; + } + + // Generate stub for disjoint short copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // elm.count: R5_ARG3 treated as signed + // + // Strategy for aligned==true: + // + // If length <= 9: + // 1. copy 2 elements at a time (l_6) + // 2. copy last element if original element count was odd (l_1) + // + // If length > 9: + // 1. copy 4 elements at a time until less than 4 elements are left (l_7) + // 2. copy 2 elements at a time until less than 2 elements are left (l_6) + // 3. copy last element if one was left in step 2. (l_1) + // + // + // Strategy for aligned==false: + // + // If length <= 9: same as aligned==true case, but NOTE: load/stores + // can be unaligned (see comment below) + // + // If length > 9: + // 1. continue with step 6. if the alignment of from and to mod 4 + // is different. + // 2. align from and to to 4 bytes by copying 1 element if necessary + // 3. at l_2 from and to are 4 byte aligned; continue with + // 5. if they cannot be aligned to 8 bytes because they have + // got different alignment mod 8. + // 4. at this point we know that both, from and to, have the same + // alignment mod 8, now copy one element if necessary to get + // 8 byte alignment of from and to. + // 5. copy 4 elements at a time until less than 4 elements are + // left; depending on step 3. all load/stores are aligned or + // either all loads or all stores are unaligned. + // 6. copy 2 elements at a time until less than 2 elements are + // left (l_6); arriving here from step 1., there is a chance + // that all accesses are unaligned. + // 7. copy last element if one was left in step 6. (l_1) + // + // There are unaligned data accesses using integer load/store + // instructions in this stub. POWER allows such accesses. + // + // According to the manuals (PowerISA_V2.06_PUBLIC, Book II, + // Chapter 2: Effect of Operand Placement on Performance) unaligned + // integer load/stores have good performance. Only unaligned + // floating point load/stores can have poor performance. + // + // TODO: + // + // 1. check if aligning the backbranch target of loops is beneficial + // + address generate_disjoint_short_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + Register tmp4 = R9_ARG7; + + address start = __ emit_fd(); + + Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8; + // don't try anything fancy if arrays don't have many elements + __ li(tmp3, 0); + __ cmpwi(CCR0, R5_ARG3, 9); + __ ble(CCR0, l_6); // copy 2 at a time + + if (!aligned) { + __ xorr(tmp1, R3_ARG1, R4_ARG2); + __ andi_(tmp1, tmp1, 3); + __ bne(CCR0, l_6); // if arrays don't have the same alignment mod 4, do 2 element copy + + // At this point it is guaranteed that both, from and to have the same alignment mod 4. + + // Copy 1 element if necessary to align to 4 bytes. + __ andi_(tmp1, R3_ARG1, 3); + __ beq(CCR0, l_2); + + __ lhz(tmp2, 0, R3_ARG1); + __ addi(R3_ARG1, R3_ARG1, 2); + __ sth(tmp2, 0, R4_ARG2); + __ addi(R4_ARG2, R4_ARG2, 2); + __ addi(R5_ARG3, R5_ARG3, -1); + __ bind(l_2); + + // At this point the positions of both, from and to, are at least 4 byte aligned. + + // Copy 4 elements at a time. + // Align to 8 bytes, but only if both, from and to, have same alignment mod 8. + __ xorr(tmp2, R3_ARG1, R4_ARG2); + __ andi_(tmp1, tmp2, 7); + __ bne(CCR0, l_7); // not same alignment mod 8 -> copy 4, either from or to will be unaligned + + // Copy a 2-element word if necessary to align to 8 bytes. + __ andi_(R0, R3_ARG1, 7); + __ beq(CCR0, l_7); + + __ lwzx(tmp2, R3_ARG1, tmp3); + __ addi(R5_ARG3, R5_ARG3, -2); + __ stwx(tmp2, R4_ARG2, tmp3); + { // FasterArrayCopy + __ addi(R3_ARG1, R3_ARG1, 4); + __ addi(R4_ARG2, R4_ARG2, 4); + } + } + + __ bind(l_7); + + // Copy 4 elements at a time; either the loads or the stores can + // be unaligned if aligned == false. + + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 15); + __ ble(CCR0, l_6); // copy 2 at a time if less than 16 elements remain + + __ srdi(tmp1, R5_ARG3, 4); + __ andi_(R5_ARG3, R5_ARG3, 15); + __ mtctr(tmp1); + + __ bind(l_8); + // Use unrolled version for mass copying (copy 16 elements a time). + // Load feeding store gets zero latency on Power6, however not on Power5. + // Therefore, the following sequence is made for the good of both. + __ ld(tmp1, 0, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp4, 24, R3_ARG1); + __ std(tmp1, 0, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp4, 24, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, 32); + __ addi(R4_ARG2, R4_ARG2, 32); + __ bdnz(l_8); + } + __ bind(l_6); + + // copy 2 elements at a time + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 2); + __ blt(CCR0, l_1); + __ srdi(tmp1, R5_ARG3, 1); + __ andi_(R5_ARG3, R5_ARG3, 1); + + __ addi(R3_ARG1, R3_ARG1, -4); + __ addi(R4_ARG2, R4_ARG2, -4); + __ mtctr(tmp1); + + __ bind(l_3); + __ lwzu(tmp2, 4, R3_ARG1); + __ stwu(tmp2, 4, R4_ARG2); + __ bdnz(l_3); + + __ addi(R3_ARG1, R3_ARG1, 4); + __ addi(R4_ARG2, R4_ARG2, 4); + } + + // do single element copy + __ bind(l_1); + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_4); + + { // FasterArrayCopy + __ mtctr(R5_ARG3); + __ addi(R3_ARG1, R3_ARG1, -2); + __ addi(R4_ARG2, R4_ARG2, -2); + + __ bind(l_5); + __ lhzu(tmp2, 2, R3_ARG1); + __ sthu(tmp2, 2, R4_ARG2); + __ bdnz(l_5); + } + __ bind(l_4); + __ blr(); + + return start; + } + + // Generate stub for conjoint short copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_conjoint_short_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + + address nooverlap_target = aligned ? + ((FunctionDescriptor*)StubRoutines::arrayof_jshort_disjoint_arraycopy())->entry() : + ((FunctionDescriptor*)StubRoutines::jshort_disjoint_arraycopy())->entry(); + + array_overlap_test(nooverlap_target, 1); + + Label l_1, l_2; + __ sldi(tmp1, R5_ARG3, 1); + __ b(l_2); + __ bind(l_1); + __ sthx(tmp2, R4_ARG2, tmp1); + __ bind(l_2); + __ addic_(tmp1, tmp1, -2); + __ lhzx(tmp2, R3_ARG1, tmp1); + __ bge(CCR0, l_1); + + __ blr(); + + return start; + } + + // Generate core code for disjoint int copy (and oop copy on 32-bit). If "aligned" + // is true, the "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + void generate_disjoint_int_copy_core(bool aligned) { + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + Register tmp4 = R0; + + Label l_1, l_2, l_3, l_4, l_5, l_6; + // for short arrays, just do single element copy + __ li(tmp3, 0); + __ cmpwi(CCR0, R5_ARG3, 5); + __ ble(CCR0, l_2); + + if (!aligned) { + // check if arrays have same alignment mod 8. + __ xorr(tmp1, R3_ARG1, R4_ARG2); + __ andi_(R0, tmp1, 7); + // Not the same alignment, but ld and std just need to be 4 byte aligned. + __ bne(CCR0, l_4); // to OR from is 8 byte aligned -> copy 2 at a time + + // copy 1 element to align to and from on an 8 byte boundary + __ andi_(R0, R3_ARG1, 7); + __ beq(CCR0, l_4); + + __ lwzx(tmp2, R3_ARG1, tmp3); + __ addi(R5_ARG3, R5_ARG3, -1); + __ stwx(tmp2, R4_ARG2, tmp3); + { // FasterArrayCopy + __ addi(R3_ARG1, R3_ARG1, 4); + __ addi(R4_ARG2, R4_ARG2, 4); + } + __ bind(l_4); + } + + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 7); + __ ble(CCR0, l_2); // copy 1 at a time if less than 8 elements remain + + __ srdi(tmp1, R5_ARG3, 3); + __ andi_(R5_ARG3, R5_ARG3, 7); + __ mtctr(tmp1); + + __ bind(l_6); + // Use unrolled version for mass copying (copy 8 elements a time). + // Load feeding store gets zero latency on power6, however not on power 5. + // Therefore, the following sequence is made for the good of both. + __ ld(tmp1, 0, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp4, 24, R3_ARG1); + __ std(tmp1, 0, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp4, 24, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, 32); + __ addi(R4_ARG2, R4_ARG2, 32); + __ bdnz(l_6); + } + + // copy 1 element at a time + __ bind(l_2); + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_1); + + { // FasterArrayCopy + __ mtctr(R5_ARG3); + __ addi(R3_ARG1, R3_ARG1, -4); + __ addi(R4_ARG2, R4_ARG2, -4); + + __ bind(l_3); + __ lwzu(tmp2, 4, R3_ARG1); + __ stwu(tmp2, 4, R4_ARG2); + __ bdnz(l_3); + } + + __ bind(l_1); + return; + } + + // Generate stub for disjoint int copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_disjoint_int_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + generate_disjoint_int_copy_core(aligned); + __ blr(); + return start; + } + + // Generate core code for conjoint int copy (and oop copy on + // 32-bit). If "aligned" is true, the "from" and "to" addresses + // are assumed to be heapword aligned. + // + // Arguments: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + void generate_conjoint_int_copy_core(bool aligned) { + // Do reverse copy. We assume the case of actual overlap is rare enough + // that we don't have to optimize it. + + Label l_1, l_2, l_3, l_4, l_5, l_6; + + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + Register tmp4 = R0; + + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_6); + + __ sldi(R5_ARG3, R5_ARG3, 2); + __ add(R3_ARG1, R3_ARG1, R5_ARG3); + __ add(R4_ARG2, R4_ARG2, R5_ARG3); + __ srdi(R5_ARG3, R5_ARG3, 2); + + __ cmpwi(CCR0, R5_ARG3, 7); + __ ble(CCR0, l_5); // copy 1 at a time if less than 8 elements remain + + __ srdi(tmp1, R5_ARG3, 3); + __ andi(R5_ARG3, R5_ARG3, 7); + __ mtctr(tmp1); + + __ bind(l_4); + // Use unrolled version for mass copying (copy 4 elements a time). + // Load feeding store gets zero latency on Power6, however not on Power5. + // Therefore, the following sequence is made for the good of both. + __ addi(R3_ARG1, R3_ARG1, -32); + __ addi(R4_ARG2, R4_ARG2, -32); + __ ld(tmp4, 24, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp1, 0, R3_ARG1); + __ std(tmp4, 24, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp1, 0, R4_ARG2); + __ bdnz(l_4); + + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_6); + + __ bind(l_5); + __ mtctr(R5_ARG3); + __ bind(l_3); + __ lwz(R0, -4, R3_ARG1); + __ stw(R0, -4, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, -4); + __ addi(R4_ARG2, R4_ARG2, -4); + __ bdnz(l_3); + + __ bind(l_6); + } + } + + // Generate stub for conjoint int copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_conjoint_int_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + address nooverlap_target = aligned ? + ((FunctionDescriptor*)StubRoutines::arrayof_jint_disjoint_arraycopy())->entry() : + ((FunctionDescriptor*)StubRoutines::jint_disjoint_arraycopy())->entry(); + + array_overlap_test(nooverlap_target, 2); + + generate_conjoint_int_copy_core(aligned); + + __ blr(); + + return start; + } + + // Generate core code for disjoint long copy (and oop copy on + // 64-bit). If "aligned" is true, the "from" and "to" addresses + // are assumed to be heapword aligned. + // + // Arguments: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + void generate_disjoint_long_copy_core(bool aligned) { + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + Register tmp4 = R0; + + Label l_1, l_2, l_3, l_4; + + { // FasterArrayCopy + __ cmpwi(CCR0, R5_ARG3, 3); + __ ble(CCR0, l_3); // copy 1 at a time if less than 4 elements remain + + __ srdi(tmp1, R5_ARG3, 2); + __ andi_(R5_ARG3, R5_ARG3, 3); + __ mtctr(tmp1); + + __ bind(l_4); + // Use unrolled version for mass copying (copy 4 elements a time). + // Load feeding store gets zero latency on Power6, however not on Power5. + // Therefore, the following sequence is made for the good of both. + __ ld(tmp1, 0, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp4, 24, R3_ARG1); + __ std(tmp1, 0, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp4, 24, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, 32); + __ addi(R4_ARG2, R4_ARG2, 32); + __ bdnz(l_4); + } + + // copy 1 element at a time + __ bind(l_3); + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_1); + + { // FasterArrayCopy + __ mtctr(R5_ARG3); + __ addi(R3_ARG1, R3_ARG1, -8); + __ addi(R4_ARG2, R4_ARG2, -8); + + __ bind(l_2); + __ ldu(R0, 8, R3_ARG1); + __ stdu(R0, 8, R4_ARG2); + __ bdnz(l_2); + + } + __ bind(l_1); + } + + // Generate stub for disjoint long copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_disjoint_long_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + generate_disjoint_long_copy_core(aligned); + __ blr(); + + return start; + } + + // Generate core code for conjoint long copy (and oop copy on + // 64-bit). If "aligned" is true, the "from" and "to" addresses + // are assumed to be heapword aligned. + // + // Arguments: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + void generate_conjoint_long_copy_core(bool aligned) { + Register tmp1 = R6_ARG4; + Register tmp2 = R7_ARG5; + Register tmp3 = R8_ARG6; + Register tmp4 = R0; + + Label l_1, l_2, l_3, l_4, l_5; + + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_1); + + { // FasterArrayCopy + __ sldi(R5_ARG3, R5_ARG3, 3); + __ add(R3_ARG1, R3_ARG1, R5_ARG3); + __ add(R4_ARG2, R4_ARG2, R5_ARG3); + __ srdi(R5_ARG3, R5_ARG3, 3); + + __ cmpwi(CCR0, R5_ARG3, 3); + __ ble(CCR0, l_5); // copy 1 at a time if less than 4 elements remain + + __ srdi(tmp1, R5_ARG3, 2); + __ andi(R5_ARG3, R5_ARG3, 3); + __ mtctr(tmp1); + + __ bind(l_4); + // Use unrolled version for mass copying (copy 4 elements a time). + // Load feeding store gets zero latency on Power6, however not on Power5. + // Therefore, the following sequence is made for the good of both. + __ addi(R3_ARG1, R3_ARG1, -32); + __ addi(R4_ARG2, R4_ARG2, -32); + __ ld(tmp4, 24, R3_ARG1); + __ ld(tmp3, 16, R3_ARG1); + __ ld(tmp2, 8, R3_ARG1); + __ ld(tmp1, 0, R3_ARG1); + __ std(tmp4, 24, R4_ARG2); + __ std(tmp3, 16, R4_ARG2); + __ std(tmp2, 8, R4_ARG2); + __ std(tmp1, 0, R4_ARG2); + __ bdnz(l_4); + + __ cmpwi(CCR0, R5_ARG3, 0); + __ beq(CCR0, l_1); + + __ bind(l_5); + __ mtctr(R5_ARG3); + __ bind(l_3); + __ ld(R0, -8, R3_ARG1); + __ std(R0, -8, R4_ARG2); + __ addi(R3_ARG1, R3_ARG1, -8); + __ addi(R4_ARG2, R4_ARG2, -8); + __ bdnz(l_3); + + } + __ bind(l_1); + } + + // Generate stub for conjoint long copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // + address generate_conjoint_long_copy(bool aligned, const char * name) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + address nooverlap_target = aligned ? + ((FunctionDescriptor*)StubRoutines::arrayof_jlong_disjoint_arraycopy())->entry() : + ((FunctionDescriptor*)StubRoutines::jlong_disjoint_arraycopy())->entry(); + + array_overlap_test(nooverlap_target, 3); + generate_conjoint_long_copy_core(aligned); + + __ blr(); + + return start; + } + + // Generate stub for conjoint oop copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // dest_uninitialized: G1 support + // + address generate_conjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) { + StubCodeMark mark(this, "StubRoutines", name); + + address start = __ emit_fd(); + + address nooverlap_target = aligned ? + ((FunctionDescriptor*)StubRoutines::arrayof_oop_disjoint_arraycopy())->entry() : + ((FunctionDescriptor*)StubRoutines::oop_disjoint_arraycopy())->entry(); + + gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7); + + // Save arguments. + __ mr(R9_ARG7, R4_ARG2); + __ mr(R10_ARG8, R5_ARG3); + + if (UseCompressedOops) { + array_overlap_test(nooverlap_target, 2); + generate_conjoint_int_copy_core(aligned); + } else { + array_overlap_test(nooverlap_target, 3); + generate_conjoint_long_copy_core(aligned); + } + + gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1); + + __ blr(); + + return start; + } + + // Generate stub for disjoint oop copy. If "aligned" is true, the + // "from" and "to" addresses are assumed to be heapword aligned. + // + // Arguments for generated stub: + // from: R3_ARG1 + // to: R4_ARG2 + // count: R5_ARG3 treated as signed + // dest_uninitialized: G1 support + // + address generate_disjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) { + StubCodeMark mark(this, "StubRoutines", name); + address start = __ emit_fd(); + + gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7); + + // save some arguments, disjoint_long_copy_core destroys them. + // needed for post barrier + __ mr(R9_ARG7, R4_ARG2); + __ mr(R10_ARG8, R5_ARG3); + + if (UseCompressedOops) { + generate_disjoint_int_copy_core(aligned); + } else { + generate_disjoint_long_copy_core(aligned); + } + + gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1); + + __ blr(); + + return start; + } + + void generate_arraycopy_stubs() { + // Note: the disjoint stubs must be generated first, some of + // the conjoint stubs use them. + + // non-aligned disjoint versions + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy"); + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy"); + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, "jlong_disjoint_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, "oop_disjoint_arraycopy", false); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(false, "oop_disjoint_arraycopy_uninit", true); + + // aligned disjoint versions + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, "arrayof_jbyte_disjoint_arraycopy"); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, "arrayof_jshort_disjoint_arraycopy"); + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, "arrayof_jint_disjoint_arraycopy"); + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, "arrayof_jlong_disjoint_arraycopy"); + StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, "arrayof_oop_disjoint_arraycopy", false); + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(true, "oop_disjoint_arraycopy_uninit", true); + + // non-aligned conjoint versions + StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy"); + StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); + StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy"); + StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, "jlong_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, "oop_arraycopy", false); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(false, "oop_arraycopy_uninit", true); + + // aligned conjoint versions + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, "arrayof_jbyte_arraycopy"); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy"); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy"); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, "arrayof_jlong_arraycopy"); + StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", false); + StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", true); + + // fill routines + StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); + StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); + StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); + StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); + StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); + StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); + } + + // Safefetch stubs. + void generate_safefetch(const char* name, int size, address* entry, address* fault_pc, address* continuation_pc) { + // safefetch signatures: + // int SafeFetch32(int* adr, int errValue); + // intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue); + // + // arguments: + // R3_ARG1 = adr + // R4_ARG2 = errValue + // + // result: + // R3_RET = *adr or errValue + + StubCodeMark mark(this, "StubRoutines", name); + + // Entry point, pc or function descriptor. + *entry = __ emit_fd(); + + // Load *adr into R4_ARG2, may fault. + *fault_pc = __ pc(); + switch (size) { + case 4: + // int32_t, signed extended + __ lwa(R4_ARG2, 0, R3_ARG1); + break; + case 8: + // int64_t + __ ld(R4_ARG2, 0, R3_ARG1); + break; + default: + ShouldNotReachHere(); + } + + // return errValue or *adr + *continuation_pc = __ pc(); + __ mr(R3_RET, R4_ARG2); + __ blr(); + } + + // Initialization + void generate_initial() { + // Generates all stubs and initializes the entry points + + // Entry points that exist in all platforms. + // Note: This is code that could be shared among different platforms - however the + // benefit seems to be smaller than the disadvantage of having a + // much more complicated generator structure. See also comment in + // stubRoutines.hpp. + + StubRoutines::_forward_exception_entry = generate_forward_exception(); + StubRoutines::_call_stub_entry = generate_call_stub(StubRoutines::_call_stub_return_address); + StubRoutines::_catch_exception_entry = generate_catch_exception(); + } + + void generate_all() { + // Generates all stubs and initializes the entry points + + // These entry points require SharedInfo::stack0 to be set up in + // non-core builds + StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); + // Handle IncompatibleClassChangeError in itable stubs. + StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); + StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); + StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); + + StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); + + // support for verify_oop (must happen after universe_init) + StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); + + // arraycopy stubs used by compilers + generate_arraycopy_stubs(); + + // PPC uses stubs for safefetch. + generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, + &StubRoutines::_safefetch32_fault_pc, + &StubRoutines::_safefetch32_continuation_pc); + generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry, + &StubRoutines::_safefetchN_fault_pc, + &StubRoutines::_safefetchN_continuation_pc); + } + + public: + StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { + // replace the standard masm with a special one: + _masm = new MacroAssembler(code); + if (all) { + generate_all(); + } else { + generate_initial(); + } + } +}; + +void StubGenerator_generate(CodeBuffer* code, bool all) { + StubGenerator g(code, all); +} diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp new file mode 100644 index 00000000000..47735a8b1ba --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/deoptimization.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/stubRoutines.hpp" +#ifdef TARGET_OS_FAMILY_aix +# include "thread_aix.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_linux +# include "thread_linux.inline.hpp" +#endif + +// Implementation of the platform-specific part of StubRoutines - for +// a description of how to extend it, see the stubRoutines.hpp file. + + diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp new file mode 100644 index 00000000000..d33a34650b5 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_STUBROUTINES_PPC_64_HPP +#define CPU_PPC_VM_STUBROUTINES_PPC_64_HPP + +// This file holds the platform specific parts of the StubRoutines +// definition. See stubRoutines.hpp for a description on how to +// extend it. + +static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; } + +enum platform_dependent_constants { + code_size1 = 20000, // simply increase if too small (assembler will crash if too small) + code_size2 = 20000 // simply increase if too small (assembler will crash if too small) +}; + +#endif // CPU_PPC_VM_STUBROUTINES_PPC_64_HPP diff --git a/hotspot/src/cpu/ppc/vm/vmStructs_ppc.hpp b/hotspot/src/cpu/ppc/vm/vmStructs_ppc.hpp new file mode 100644 index 00000000000..bb4db41095d --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vmStructs_ppc.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_VMSTRUCTS_PPC_HPP +#define CPU_PPC_VM_VMSTRUCTS_PPC_HPP + +// These are the CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) + +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) + +#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // CPU_PPC_VM_VMSTRUCTS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp new file mode 100644 index 00000000000..079b781d655 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -0,0 +1,472 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "assembler_ppc.inline.hpp" +#include "compiler/disassembler.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/java.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "utilities/defaultStream.hpp" +#include "vm_version_ppc.hpp" +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_linux +# include "os_linux.inline.hpp" +#endif + +# include + +int VM_Version::_features = VM_Version::unknown_m; +int VM_Version::_measured_cache_line_size = 128; // default value +const char* VM_Version::_features_str = ""; +bool VM_Version::_is_determine_features_test_running = false; + + +#define MSG(flag) \ + if (flag && !FLAG_IS_DEFAULT(flag)) \ + jio_fprintf(defaultStream::error_stream(), \ + "warning: -XX:+" #flag " requires -XX:+UseSIGTRAP\n" \ + " -XX:+" #flag " will be disabled!\n"); + +void VM_Version::initialize() { + + // Test which instructions are supported and measure cache line size. + determine_features(); + + // If PowerArchitecturePPC64 hasn't been specified explicitly determine from features. + if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) { + if (VM_Version::has_popcntw()) { + FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7); + } else if (VM_Version::has_cmpb()) { + FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 6); + } else if (VM_Version::has_popcntb()) { + FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 5); + } else { + FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 0); + } + } + guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 || + PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7, + "PowerArchitecturePPC64 should be 0, 5, 6 or 7"); + + if (!UseSIGTRAP) { + MSG(TrapBasedICMissChecks); + MSG(TrapBasedNotEntrantChecks); + MSG(TrapBasedNullChecks); + MSG(TrapBasedRangeChecks); + FLAG_SET_ERGO(bool, TrapBasedNotEntrantChecks, false); + FLAG_SET_ERGO(bool, TrapBasedNullChecks, false); + FLAG_SET_ERGO(bool, TrapBasedICMissChecks, false); + FLAG_SET_ERGO(bool, TrapBasedRangeChecks, false); + } + +#ifdef COMPILER2 + // On Power6 test for section size. + if (PowerArchitecturePPC64 == 6) + determine_section_size(); + // TODO: PPC port else + // TODO: PPC port PdScheduling::power6SectorSize = 0x20; + + MaxVectorSize = 8; +#endif + + // Create and print feature-string. + char buf[(num_features+1) * 16]; // max 16 chars per feature + jio_snprintf(buf, sizeof(buf), + "ppc64%s%s%s%s%s%s%s%s", + (has_fsqrt() ? " fsqrt" : ""), + (has_isel() ? " isel" : ""), + (has_lxarxeh() ? " lxarxeh" : ""), + (has_cmpb() ? " cmpb" : ""), + //(has_mftgpr()? " mftgpr" : ""), + (has_popcntb() ? " popcntb" : ""), + (has_popcntw() ? " popcntw" : ""), + (has_fcfids() ? " fcfids" : ""), + (has_vand() ? " vand" : "") + // Make sure number of %s matches num_features! + ); + _features_str = strdup(buf); + NOT_PRODUCT(if (Verbose) print_features();); + + // PPC64 supports 8-byte compare-exchange operations (see + // Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr) + // and 'atomic long memory ops' (see Unsafe_GetLongVolatile). + _supports_cx8 = true; + + UseSSE = 0; // Only on x86 and x64 + + intx cache_line_size = _measured_cache_line_size; + + if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) AllocatePrefetchStyle = 1; + + if (AllocatePrefetchStyle == 4) { + AllocatePrefetchStepSize = cache_line_size; // need exact value + if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 12; // use larger blocks by default + if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 2*cache_line_size; // default is not defined ? + } else { + if (cache_line_size > AllocatePrefetchStepSize) AllocatePrefetchStepSize = cache_line_size; + if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 3; // Optimistic value + if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 3*cache_line_size; // default is not defined ? + } + + assert(AllocatePrefetchLines > 0, "invalid value"); + if (AllocatePrefetchLines < 1) // Set valid value in product VM. + AllocatePrefetchLines = 1; // Conservative value + + if (AllocatePrefetchStyle == 3 && AllocatePrefetchDistance < cache_line_size) + AllocatePrefetchStyle = 1; // fall back if inappropriate + + assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); +} + +void VM_Version::print_features() { + tty->print_cr("Version: %s cache_line_size = %d", cpu_features(), get_cache_line_size()); +} + +#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->emit_fd(); + + 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->emit_fd(); + // 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(); + + 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) { + ttyLocker ttyl; + tty->print_cr("Decoding section size detection stub at " INTPTR_FORMAT " before execution:", code); + Disassembler::decode((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() { + const int code_size = (num_features+1+2*7)*BytesPerInstWord; // 7 InstWords for each call (function descriptor + blr instruction) + int features = 0; + + // create test area + enum { BUFFER_SIZE = 2*4*K }; // needs to be >=2* max cache line size (cache line size can't exceed min page size) + char test_area[BUFFER_SIZE]; + char *mid_of_test_area = &test_area[BUFFER_SIZE>>1]; + + // Allocate space for the code + ResourceMark rm; + CodeBuffer cb("detect_cpu_features", code_size, 0); + MacroAssembler* a = new MacroAssembler(&cb); + + // emit code. + void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->emit_fd(); + uint32_t *code = (uint32_t *)a->pc(); + // Don't use R0 in ldarx. + // keep R3_ARG1 = R3 unmodified, it contains &field (see below) + // keep R4_ARG2 = R4 unmodified, it contains offset = 0 (see below) + a->fsqrt(F3, F4); // code[0] -> fsqrt_m + a->isel(R7, R5, R6, 0); // code[1] -> isel_m + a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1);// code[2] -> lxarx_m + a->cmpb(R7, R5, R6); // code[3] -> bcmp + //a->mftgpr(R7, F3); // code[4] -> mftgpr + a->popcntb(R7, R5); // code[5] -> popcntb + a->popcntw(R7, R5); // code[6] -> popcntw + a->fcfids(F3, F4); // code[7] -> fcfids + a->vand(VR0, VR0, VR0); // code[8] -> vand + a->blr(); + + // Emit function to set one cache line to zero + void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->emit_fd(); // emit function descriptor and get pointer to it + a->dcbz(R3_ARG1); // R3_ARG1 = R3 = addr + a->blr(); + + uint32_t *code_end = (uint32_t *)a->pc(); + a->flush(); + + // Print the detection code. + if (PrintAssembly) { + ttyLocker ttyl; + tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " before execution:", code); + Disassembler::decode((u_char*)code, (u_char*)code_end, tty); + } + + // Measure cache line size. + memset(test_area, 0xFF, BUFFER_SIZE); // fill test area with 0xFF + (*zero_cacheline_func_ptr)(mid_of_test_area); // call function which executes dcbz to the middle + int count = 0; // count zeroed bytes + for (int i = 0; i < BUFFER_SIZE; i++) if (test_area[i] == 0) count++; + guarantee(is_power_of_2(count), "cache line size needs to be a power of 2"); + _measured_cache_line_size = count; + + // Execute code. Illegal instructions will be replaced by 0 in the signal handler. + VM_Version::_is_determine_features_test_running = true; + (*test)((address)mid_of_test_area, (uint64_t)0); + VM_Version::_is_determine_features_test_running = false; + + // determine which instructions are legal. + int feature_cntr = 0; + if (code[feature_cntr++]) features |= fsqrt_m; + if (code[feature_cntr++]) features |= isel_m; + if (code[feature_cntr++]) features |= lxarxeh_m; + if (code[feature_cntr++]) features |= cmpb_m; + //if(code[feature_cntr++])features |= mftgpr_m; + if (code[feature_cntr++]) features |= popcntb_m; + if (code[feature_cntr++]) features |= popcntw_m; + if (code[feature_cntr++]) features |= fcfids_m; + if (code[feature_cntr++]) features |= vand_m; + + // Print the detection code. + if (PrintAssembly) { + ttyLocker ttyl; + tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " after execution:", code); + Disassembler::decode((u_char*)code, (u_char*)code_end, tty); + } + + _features = features; +} + + +static int saved_features = 0; + +void VM_Version::allow_all() { + saved_features = _features; + _features = all_features_m; +} + +void VM_Version::revert() { + _features = saved_features; +} diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp new file mode 100644 index 00000000000..59553a6bb0e --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_VM_VERSION_PPC_HPP +#define CPU_PPC_VM_VM_VERSION_PPC_HPP + +#include "runtime/globals_extension.hpp" +#include "runtime/vm_version.hpp" + +class VM_Version: public Abstract_VM_Version { +protected: + enum Feature_Flag { + fsqrt, + isel, + lxarxeh, + cmpb, + popcntb, + popcntw, + fcfids, + vand, + dcba, + num_features // last entry to count features + }; + enum Feature_Flag_Set { + unknown_m = 0, + fsqrt_m = (1 << fsqrt ), + isel_m = (1 << isel ), + lxarxeh_m = (1 << lxarxeh), + cmpb_m = (1 << cmpb ), + popcntb_m = (1 << popcntb), + popcntw_m = (1 << popcntw), + fcfids_m = (1 << fcfids ), + vand_m = (1 << vand ), + dcba_m = (1 << dcba ), + all_features_m = -1 + }; + static int _features; + static int _measured_cache_line_size; + static const char* _features_str; + static bool _is_determine_features_test_running; + + static void print_features(); + static void determine_features(); // also measures cache line size + static void determine_section_size(); + static void power6_micro_bench(); +public: + // Initialization + static void initialize(); + + static bool is_determine_features_test_running() { return _is_determine_features_test_running; } + // CPU instruction support + static bool has_fsqrt() { return (_features & fsqrt_m) != 0; } + static bool has_isel() { return (_features & isel_m) != 0; } + static bool has_lxarxeh() { return (_features & lxarxeh_m) !=0; } + static bool has_cmpb() { return (_features & cmpb_m) != 0; } + static bool has_popcntb() { return (_features & popcntb_m) != 0; } + static bool has_popcntw() { return (_features & popcntw_m) != 0; } + static bool has_fcfids() { return (_features & fcfids_m) != 0; } + static bool has_vand() { return (_features & vand_m) != 0; } + static bool has_dcba() { return (_features & dcba_m) != 0; } + + static const char* cpu_features() { return _features_str; } + + static int get_cache_line_size() { return _measured_cache_line_size; } + + // Assembler testing + static void allow_all(); + static void revert(); +}; + +#endif // CPU_PPC_VM_VM_VERSION_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/vmreg_ppc.cpp b/hotspot/src/cpu/ppc/vm/vmreg_ppc.cpp new file mode 100644 index 00000000000..a2a83f2f361 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vmreg_ppc.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "code/vmreg.hpp" + +void VMRegImpl::set_regName() { + Register reg = ::as_Register(0); + int i; + for (i = 0; i < ConcreteRegisterImpl::max_gpr; ) { + regName[i++] = reg->name(); + regName[i++] = reg->name(); + if (reg->encoding() < RegisterImpl::number_of_registers-1) + reg = reg->successor(); + } + + FloatRegister freg = ::as_FloatRegister(0); + for ( ; i < ConcreteRegisterImpl::max_fpr; ) { + regName[i++] = freg->name(); + regName[i++] = freg->name(); + if (reg->encoding() < FloatRegisterImpl::number_of_registers-1) + freg = freg->successor(); + } + for ( ; i < ConcreteRegisterImpl::number_of_registers; i++) { + regName[i] = "NON-GPR-FPR"; + } +} + diff --git a/hotspot/src/cpu/ppc/vm/vmreg_ppc.hpp b/hotspot/src/cpu/ppc/vm/vmreg_ppc.hpp new file mode 100644 index 00000000000..92c4d088de8 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vmreg_ppc.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_VMREG_PPC_HPP +#define CPU_PPC_VM_VMREG_PPC_HPP + + bool is_Register(); + Register as_Register(); + + bool is_FloatRegister(); + FloatRegister as_FloatRegister(); + +#endif // CPU_PPC_VM_VMREG_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/vmreg_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/vmreg_ppc.inline.hpp new file mode 100644 index 00000000000..d097c5bc5cb --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vmreg_ppc.inline.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_VMREG_PPC_INLINE_HPP +#define CPU_PPC_VM_VMREG_PPC_INLINE_HPP + +inline VMReg RegisterImpl::as_VMReg() { + if (this == noreg) return VMRegImpl::Bad(); + return VMRegImpl::as_VMReg(encoding() << 1); +} + +// Since we don't have two halfs here, don't multiply by 2. +inline VMReg ConditionRegisterImpl::as_VMReg() { + return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_fpr); +} + +inline VMReg FloatRegisterImpl::as_VMReg() { + return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); +} + +inline VMReg SpecialRegisterImpl::as_VMReg() { + return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_cnd); +} + +inline bool VMRegImpl::is_Register() { + return (unsigned int)value() < (unsigned int)ConcreteRegisterImpl::max_gpr; +} + +inline bool VMRegImpl::is_FloatRegister() { + return value() >= ConcreteRegisterImpl::max_gpr && + value() < ConcreteRegisterImpl::max_fpr; +} + +inline Register VMRegImpl::as_Register() { + assert(is_Register() && is_even(value()), "even-aligned GPR name"); + return ::as_Register(value()>>1); +} + +inline FloatRegister VMRegImpl::as_FloatRegister() { + assert(is_FloatRegister() && is_even(value()), "must be"); + return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); +} + +inline bool VMRegImpl::is_concrete() { + assert(is_reg(), "must be"); + return is_even(value()); +} + +#endif // CPU_PPC_VM_VMREG_PPC_INLINE_HPP diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp new file mode 100644 index 00000000000..1b2af584e12 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/vtableStubs.hpp" +#include "interp_masm_ppc_64.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klassVtable.hpp" +#include "runtime/sharedRuntime.hpp" +#include "vmreg_ppc.inline.hpp" +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +#define __ masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) // nothing +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +#ifndef PRODUCT +extern "C" void bad_compiled_vtable_index(JavaThread* thread, oopDesc* receiver, int index); +#endif + +// Used by compiler only; may use only caller saved, non-argument +// registers. +VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { + // PPC port: use fixed size. + const int code_length = VtableStub::pd_code_size_limit(true); + VtableStub* s = new (code_length) VtableStub(true, vtable_index); + ResourceMark rm; + CodeBuffer cb(s->entry_point(), code_length); + MacroAssembler* masm = new MacroAssembler(&cb); + address start_pc; + +#ifndef PRODUCT + if (CountCompiledCalls) { + __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); + __ lwz(R12_scratch2, 0, R11_scratch1); + __ addi(R12_scratch2, R12_scratch2, 1); + __ stw(R12_scratch2, 0, R11_scratch1); + } +#endif + + assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1"); + + // Get receiver klass. + const Register rcvr_klass = R11_scratch1; + + // We might implicit NULL fault here. + address npe_addr = __ pc(); // npe = null pointer exception + __ load_klass_with_trap_null_check(rcvr_klass, R3); + + // Set methodOop (in case of interpreted method), and destination address. + int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); + +#ifndef PRODUCT + if (DebugVtables) { + Label L; + // Check offset vs vtable length. + const Register vtable_len = R12_scratch2; + __ lwz(vtable_len, InstanceKlass::vtable_length_offset()*wordSize, rcvr_klass); + __ cmpwi(CCR0, vtable_len, vtable_index*vtableEntry::size()); + __ bge(CCR0, L); + __ li(R12_scratch2, vtable_index); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), R3_ARG1, R12_scratch2, false); + __ bind(L); + } +#endif + + int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); + + __ ld(R19_method, v_off, rcvr_klass); + +#ifndef PRODUCT + if (DebugVtables) { + Label L; + __ cmpdi(CCR0, R19_method, 0); + __ bne(CCR0, L); + __ stop("Vtable entry is ZERO", 102); + __ bind(L); + } +#endif + + // If the vtable entry is null, the method is abstract. + address ame_addr = __ pc(); // ame = abstract method error + + __ ld_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); + __ mtctr(R12_scratch2); + __ bctr(); + masm->flush(); + + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); + + s->set_exception_points(npe_addr, ame_addr); + + return s; +} + +VtableStub* VtableStubs::create_itable_stub(int vtable_index) { + // PPC port: use fixed size. + const int code_length = VtableStub::pd_code_size_limit(false); + VtableStub* s = new (code_length) VtableStub(false, vtable_index); + ResourceMark rm; + CodeBuffer cb(s->entry_point(), code_length); + MacroAssembler* masm = new MacroAssembler(&cb); + address start_pc; + +#ifndef PRODUCT + if (CountCompiledCalls) { + __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); + __ lwz(R12_scratch2, 0, R11_scratch1); + __ addi(R12_scratch2, R12_scratch2, 1); + __ stw(R12_scratch2, 0, R11_scratch1); + } +#endif + + assert(VtableStub::receiver_location() == R3_ARG1->as_VMReg(), "receiver expected in R3_ARG1"); + + // Entry arguments: + // R19_method: Interface + // R3_ARG1: Receiver + // + + const Register rcvr_klass = R11_scratch1; + const Register vtable_len = R12_scratch2; + const Register itable_entry_addr = R21_tmp1; + const Register itable_interface = R22_tmp2; + + // Get receiver klass. + + // We might implicit NULL fault here. + address npe_addr = __ pc(); // npe = null pointer exception + __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1); + + //__ ld(rcvr_klass, oopDesc::klass_offset_in_bytes(), R3_ARG1); + + BLOCK_COMMENT("Load start of itable entries into itable_entry."); + __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass); + __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize)); + __ add(itable_entry_addr, vtable_len, rcvr_klass); + + // Loop over all itable entries until desired interfaceOop(Rinterface) found. + BLOCK_COMMENT("Increment itable_entry_addr in loop."); + const int vtable_base_offset = InstanceKlass::vtable_start_offset() * wordSize; + __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes()); + + const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; + Label search; + __ bind(search); + __ ld(itable_interface, 0, itable_entry_addr); + + // Handle IncompatibleClassChangeError in itable stubs. + // If the entry is NULL then we've reached the end of the table + // without finding the expected interface, so throw an exception. + BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs."); + Label throw_icce; + __ cmpdi(CCR1, itable_interface, 0); + __ cmpd(CCR0, itable_interface, R19_method); + __ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc); + __ beq(CCR1, throw_icce); + __ bne(CCR0, search); + + // Entry found and itable_entry_addr points to it, get offset of vtable for interface. + + const Register vtable_offset = R12_scratch2; + const Register itable_method = R11_scratch1; + + const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - + itableOffsetEntry::interface_offset_in_bytes()) - + itable_offset_search_inc; + __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr); + + // Compute itableMethodEntry and get methodOop and entry point for compiler. + const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + + itableMethodEntry::method_offset_in_bytes(); + + __ add(itable_method, rcvr_klass, vtable_offset); + __ ld(R19_method, method_offset, itable_method); + +#ifndef PRODUCT + if (DebugVtables) { + Label ok; + __ cmpd(CCR0, R19_method, 0); + __ bne(CCR0, ok); + __ stop("methodOop is null", 103); + __ bind(ok); + } +#endif + + // If the vtable entry is null, the method is abstract. + address ame_addr = __ pc(); // ame = abstract method error + + // Must do an explicit check if implicit checks are disabled. + assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity"); + if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (TrapBasedNullChecks) { + __ trap_null_check(R19_method); + } else { + __ cmpdi(CCR0, R19_method, 0); + __ beq(CCR0, throw_icce); + } + } + __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); + __ mtctr(R12_scratch2); + __ bctr(); + + // Handle IncompatibleClassChangeError in itable stubs. + // More detailed error message. + // We force resolving of the call site by jumping to the "handle + // wrong method" stub, and so let the interpreter runtime do all the + // dirty work. + __ bind(throw_icce); + __ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub()); + __ mtctr(R11_scratch1); + __ bctr(); + + masm->flush(); + + guarantee(__ pc() <= s->code_end(), "overflowed buffer"); + + s->set_exception_points(npe_addr, ame_addr); + return s; +} + +int VtableStub::pd_code_size_limit(bool is_vtable_stub) { + if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) { + return 1000; + } else { + if (is_vtable_stub) { + return 20 + 16 + 8; // Plain + (cOops & Traps) + safety + } else { + return 16 + 96; + } + } +} + +int VtableStub::pd_code_alignment() { + const unsigned int icache_line_size = 32; + return icache_line_size; +} diff --git a/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp new file mode 100644 index 00000000000..6e522364b17 --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp @@ -0,0 +1,401 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP +#define OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP + +#include "orderAccess_linux_ppc.inline.hpp" +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#include "vm_version_ppc.hpp" + +#ifndef PPC64 +#error "Atomic currently only implemented for PPC64" +#endif + +// Implementation of class atomic + +inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } + +inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } + +inline jlong Atomic::load(volatile jlong* src) { return *src; } + +/* + machine barrier instructions: + + - sync two-way memory barrier, aka fence + - lwsync orders Store|Store, + Load|Store, + Load|Load, + but not Store|Load + - eieio orders memory accesses for device memory (only) + - isync invalidates speculatively executed instructions + From the POWER ISA 2.06 documentation: + "[...] an isync instruction prevents the execution of + instructions following the isync until instructions + preceding the isync have completed, [...]" + From IBM's AIX assembler reference: + "The isync [...] instructions causes the processor to + refetch any instructions that might have been fetched + prior to the isync instruction. The instruction isync + causes the processor to wait for all previous instructions + to complete. Then any instructions already fetched are + discarded and instruction processing continues in the + environment established by the previous instructions." + + semantic barrier instructions: + (as defined in orderAccess.hpp) + + - release orders Store|Store, (maps to lwsync) + Load|Store + - acquire orders Load|Store, (maps to lwsync) + Load|Load + - fence orders Store|Store, (maps to sync) + Load|Store, + Load|Load, + Store|Load +*/ + +#define strasm_sync "\n sync \n" +#define strasm_lwsync "\n lwsync \n" +#define strasm_isync "\n isync \n" +#define strasm_release strasm_lwsync +#define strasm_acquire strasm_lwsync +#define strasm_fence strasm_sync +#define strasm_nobarrier "" +#define strasm_nobarrier_clobber_memory "" + +inline jint Atomic::add (jint add_value, volatile jint* dest) { + + unsigned int result; + + __asm__ __volatile__ ( + strasm_lwsync + "1: lwarx %0, 0, %2 \n" + " add %0, %0, %1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_isync + : /*%0*/"=&r" (result) + : /*%1*/"r" (add_value), /*%2*/"r" (dest) + : "cc", "memory" ); + + return (jint) result; +} + + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + + long result; + + __asm__ __volatile__ ( + strasm_lwsync + "1: ldarx %0, 0, %2 \n" + " add %0, %0, %1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_isync + : /*%0*/"=&r" (result) + : /*%1*/"r" (add_value), /*%2*/"r" (dest) + : "cc", "memory" ); + + return (intptr_t) result; +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)add_ptr(add_value, (volatile intptr_t*)dest); +} + + +inline void Atomic::inc (volatile jint* dest) { + + unsigned int temp; + + __asm__ __volatile__ ( + strasm_nobarrier + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, 1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_nobarrier_clobber_memory); + +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + + long temp; + + __asm__ __volatile__ ( + strasm_nobarrier + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, 1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_nobarrier_clobber_memory); + +} + +inline void Atomic::inc_ptr(volatile void* dest) { + inc_ptr((volatile intptr_t*)dest); +} + + +inline void Atomic::dec (volatile jint* dest) { + + unsigned int temp; + + __asm__ __volatile__ ( + strasm_nobarrier + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, -1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_nobarrier_clobber_memory); + +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + + long temp; + + __asm__ __volatile__ ( + strasm_nobarrier + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, -1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_nobarrier_clobber_memory); + +} + +inline void Atomic::dec_ptr(volatile void* dest) { + dec_ptr((volatile intptr_t*)dest); +} + +inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) { + + // Note that xchg_ptr doesn't necessarily do an acquire + // (see synchronizer.cpp). + + unsigned int old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* lwsync */ + strasm_lwsync + /* atomic loop */ + "1: \n" + " lwarx %[old_value], %[dest], %[zero] \n" + " stwcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* isync */ + strasm_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jint) old_value; +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + + // Note that xchg_ptr doesn't necessarily do an acquire + // (see synchronizer.cpp). + + long old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* lwsync */ + strasm_lwsync + /* atomic loop */ + "1: \n" + " ldarx %[old_value], %[dest], %[zero] \n" + " stdcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* isync */ + strasm_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (intptr_t) old_value; +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); +} + +inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) { + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' + // (see atomic.hpp). + + unsigned int old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* fence */ + strasm_sync + /* simple guard */ + " lwz %[old_value], 0(%[dest]) \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " lwarx %[old_value], %[dest], %[zero] \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stwcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* acquire */ + strasm_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jint) old_value; +} + +inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) { + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' + // (see atomic.hpp). + + long old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* fence */ + strasm_sync + /* simple guard */ + " ld %[old_value], 0(%[dest]) \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " ldarx %[old_value], %[dest], %[zero] \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stdcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* acquire */ + strasm_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jlong) old_value; +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +#undef strasm_sync +#undef strasm_lwsync +#undef strasm_isync +#undef strasm_release +#undef strasm_acquire +#undef strasm_fence +#undef strasm_nobarrier +#undef strasm_nobarrier_clobber_memory + +#endif // OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp b/hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp new file mode 100644 index 00000000000..783ca9afb0b --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/globals_linux_ppc.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_GLOBALS_LINUX_PPC_HPP +#define OS_CPU_LINUX_PPC_VM_GLOBALS_LINUX_PPC_HPP + +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + +define_pd_global(bool, DontYieldALot, false); +define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 2048); + +// if we set CompilerThreadStackSize to a value different than 0, it will +// be used in os::create_thread(). Otherwise, due the strange logic in os::create_thread(), +// the stack size for compiler threads will default to VMThreadStackSize, although it +// is defined to 4M in os::Linux::default_stack_size()! +define_pd_global(intx, CompilerThreadStackSize, 4096); + +// Allow extra space in DEBUG builds for asserts. +define_pd_global(uintx,JVMInvokeMethodSlack, 8192); + +define_pd_global(intx, StackYellowPages, 6); +define_pd_global(intx, StackRedPages, 1); +define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+2)); + +// Only used on 64 bit platforms +define_pd_global(uintx,HeapBaseMinAddress, 2*G); +// Only used on 64 bit Windows platforms +define_pd_global(bool, UseVectoredExceptions, false); + +#endif // OS_CPU_LINUX_PPC_VM_GLOBALS_LINUX_PPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp new file mode 100644 index 00000000000..c237322232d --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_ORDERACCESS_LINUX_PPC_INLINE_HPP +#define OS_CPU_LINUX_PPC_VM_ORDERACCESS_LINUX_PPC_INLINE_HPP + +#include "runtime/orderAccess.hpp" +#include "vm_version_ppc.hpp" + +#ifndef PPC64 +#error "OrderAccess currently only implemented for PPC64" +#endif + +// Implementation of class OrderAccess. + +// +// Machine barrier instructions: +// +// - sync Two-way memory barrier, aka fence. +// - lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - eieio orders Store|Store +// - isync Invalidates speculatively executed instructions, +// but isync may complete before storage accesses +// associated with instructions preceding isync have +// been performed. +// +// Semantic barrier instructions: +// (as defined in orderAccess.hpp) +// +// - release orders Store|Store, (maps to lwsync) +// Load|Store +// - acquire orders Load|Store, (maps to lwsync) +// Load|Load +// - fence orders Store|Store, (maps to sync) +// Load|Store, +// Load|Load, +// Store|Load +// + +#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); +#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); +#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); +#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); +#define inlasm_release() inlasm_lwsync(); +#define inlasm_acquire() inlasm_lwsync(); +// Use twi-isync for load_acquire (faster than lwsync). +#define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); +#define inlasm_fence() inlasm_sync(); + +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_fence(); } + +inline void OrderAccess::acquire() { inlasm_acquire(); } +inline void OrderAccess::release() { inlasm_release(); } +inline void OrderAccess::fence() { inlasm_fence(); } + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } +inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } +inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } + +#undef inlasm_sync +#undef inlasm_lwsync +#undef inlasm_eieio +#undef inlasm_isync +#undef inlasm_release +#undef inlasm_acquire +#undef inlasm_fence + +#endif // OS_CPU_LINUX_PPC_VM_ORDERACCESS_LINUX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp new file mode 100644 index 00000000000..10b26495c59 --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -0,0 +1,607 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file hat + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// no precompiled headers +#include "assembler_ppc.inline.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_linux.h" +#include "memory/allocation.inline.hpp" +#include "mutex_linux.inline.hpp" +#include "nativeInst_ppc.hpp" +#include "os_share_linux.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/osThread.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/timer.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" + +// put OS-includes here +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + + +address os::current_stack_pointer() { + intptr_t* csp; + + // inline assembly `mr regno(csp), R1_SP': + __asm__ __volatile__ ("mr %0, 1":"=r"(csp):); + + return (address) csp; +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + // even in its subfields (as defined by the CPU immediate fields, + // if the CPU splits constants across multiple instructions). + + return (char*) -1; +} + +void os::initialize_thread(Thread *thread) { } + +// Frame information (pc, sp, fp) retrieved via ucontext +// always looks like a C-frame according to the frame +// conventions in frame_ppc64.hpp. +address os::Linux::ucontext_get_pc(ucontext_t * uc) { + // On powerpc64, ucontext_t is not selfcontained but contains + // a pointer to an optional substructure (mcontext_t.regs) containing the volatile + // registers - NIP, among others. + // This substructure may or may not be there depending where uc came from: + // - if uc was handed over as the argument to a sigaction handler, a pointer to the + // substructure was provided by the kernel when calling the signal handler, and + // regs->nip can be accessed. + // - if uc was filled by getcontext(), it is undefined - getcontext() does not fill + // it because the volatile registers are not needed to make setcontext() work. + // Hopefully it was zero'd out beforehand. + guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_get_pc in sigaction context"); + return (address)uc->uc_mcontext.regs->nip; +} + +intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) { + return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/]; +} + +intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) { + return NULL; +} + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { + + ExtendedPC epc; + ucontext_t* uc = (ucontext_t*)ucVoid; + + if (uc != NULL) { + epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); + if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc); + } else { + // construct empty ExtendedPC for return value checking + epc = ExtendedPC(NULL); + if (ret_sp) *ret_sp = (intptr_t *)NULL; + if (ret_fp) *ret_fp = (intptr_t *)NULL; + } + + return epc; +} + +frame os::fetch_frame_from_context(void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, epc.pc()); +} + +frame os::get_sender_for_C_frame(frame* fr) { + if (*fr->sp() == 0) { + // fr is the last C frame + return frame(NULL, NULL); + } + return frame(fr->sender_sp(), fr->sender_pc()); +} + + +frame os::current_frame() { + intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer()); + // hack. + frame topframe(csp, (address)0x8); + // return sender of current topframe which hopefully has pc != NULL. + return os::get_sender_for_C_frame(&topframe); +} + +// Utility functions + +extern "C" JNIEXPORT int +JVM_handle_linux_signal(int sig, + siginfo_t* info, + void* ucVoid, + int abort_if_unrecognized) { + ucontext_t* uc = (ucontext_t*) ucVoid; + + Thread* t = ThreadLocalStorage::get_thread_slow(); + + SignalHandlerMark shm(t); + + // Note: it's not uncommon that JNI code uses signal/sigset to install + // then restore certain signal handler (e.g. to temporarily block SIGPIPE, + // or have a SIGILL handler when detecting CPU type). When that happens, + // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To + // avoid unnecessary crash when libjsig is not preloaded, try handle signals + // that do not require siginfo/ucontext first. + + if (sig == SIGPIPE) { + if (os::Linux::chained_handler(sig, info, ucVoid)) { + return true; + } else { + if (PrintMiscellaneous && (WizardMode || Verbose)) { + warning("Ignoring SIGPIPE - see bug 4229104"); + } + return true; + } + } + + JavaThread* thread = NULL; + VMThread* vmthread = NULL; + if (os::Linux::signal_handlers_are_installed) { + if (t != NULL) { + if(t->is_Java_thread()) { + thread = (JavaThread*)t; + } else if(t->is_VM_thread()) { + vmthread = (VMThread *)t; + } + } + } + + // Moved SafeFetch32 handling outside thread!=NULL conditional block to make + // it work if no associated JavaThread object exists. + if (uc) { + address const pc = os::Linux::ucontext_get_pc(uc); + if (pc && StubRoutines::is_safefetch_fault(pc)) { + uc->uc_mcontext.regs->nip = (unsigned long)StubRoutines::continuation_for_safefetch_fault(pc); + return true; + } + } + + // decide if this trap can be handled by a stub + address stub = NULL; + address pc = NULL; + + //%note os_trap_1 + if (info != NULL && uc != NULL && thread != NULL) { + pc = (address) os::Linux::ucontext_get_pc(uc); + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV) { + // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see + // comment below). Use get_stack_bang_address instead of si_addr. + address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc); + + // Check if fault address is within thread stack. + if (addr < thread->stack_base() && + addr >= thread->stack_base() - thread->stack_size()) { + // stack overflow + if (thread->in_stack_yellow_zone(addr)) { + thread->disable_stack_yellow_zone(); + if (thread->thread_state() == _thread_in_Java) { + // Throw a stack overflow exception. + // Guard pages will be reenabled while unwinding the stack. + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); + } else { + // Thread was in the vm or native code. Return and try to finish. + return 1; + } + } else if (thread->in_stack_red_zone(addr)) { + // Fatal red zone violation. Disable the guard pages and fall through + // to handle_unexpected_exception way down below. + thread->disable_stack_red_zone(); + tty->print_raw_cr("An irrecoverable stack overflow has occurred."); + + // This is a likely cause, but hard to verify. Let's just print + // it as a hint. + tty->print_raw_cr("Please check if any of your loaded .so files has " + "enabled executable stack (see man page execstack(8))"); + } else { + // Accessing stack address below sp may cause SEGV if current + // thread has MAP_GROWSDOWN stack. This should only happen when + // current thread was created by user code with MAP_GROWSDOWN flag + // and then attached to VM. See notes in os_linux.cpp. + if (thread->osthread()->expanding_stack() == 0) { + thread->osthread()->set_expanding_stack(); + if (os::Linux::manually_expand_stack(thread, addr)) { + thread->osthread()->clear_expanding_stack(); + return 1; + } + thread->osthread()->clear_expanding_stack(); + } else { + fatal("recursive segv. expanding stack."); + } + } + } + } + + if (thread->thread_state() == _thread_in_Java) { + // Java thread running in Java code => find exception handler if any + // a fault inside compiled code, the interpreter, or a stub + + // A VM-related SIGILL may only occur if we are not in the zero page. + // On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else + // in the zero page, because it is filled with 0x0. We ignore + // explicit SIGILLs in the zero page. + if (sig == SIGILL && (pc < (address) 0x200)) { + if (TraceTraps) + tty->print_raw_cr("SIGILL happened inside zero page."); + goto report_and_die; + } + + // Handle signal from NativeJump::patch_verified_entry(). + if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) || + (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) { + if (TraceTraps) + tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + stub = SharedRuntime::get_handle_wrong_method_stub(); + } + + else if (sig == SIGSEGV && + // A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults + // in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6), + // especially when we try to read from the safepoint polling page. So the check + // (address)info->si_addr == os::get_standard_polling_page() + // doesn't work for us. We use: + ((NativeInstruction*)pc)->is_safepoint_poll()) { + if (TraceTraps) + tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc); + stub = SharedRuntime::get_poll_stub(pc); + } + + // SIGTRAP-based ic miss check in compiled code. + else if (sig == SIGTRAP && TrapBasedICMissChecks && + nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) { + if (TraceTraps) + tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::get_ic_miss_stub(); + } + + // SIGTRAP-based implicit null check in compiled code. + else if (sig == SIGTRAP && TrapBasedNullChecks && + nativeInstruction_at(pc)->is_sigtrap_null_check()) { + if (TraceTraps) + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } + + // SIGSEGV-based implicit null check in compiled code. + else if (sig == SIGSEGV && ImplicitNullChecks && + CodeCache::contains((void*) pc) && + !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) { + if (TraceTraps) + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } + +#ifdef COMPILER2 + // SIGTRAP-based implicit range check in compiled code. + else if (sig == SIGTRAP && TrapBasedRangeChecks && + nativeInstruction_at(pc)->is_sigtrap_range_check()) { + if (TraceTraps) + tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } +#endif + else if (sig == SIGBUS) { + // BugId 4454115: A read from a MappedByteBuffer can fault here if the + // underlying file has been truncated. Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL; + if (nm != NULL && nm->has_unsafe_access()) { + // We don't really need a stub here! Just set the pending exeption and + // continue at the next instruction after the faulting read. Returning + // garbage from this read is ok. + thread->set_pending_unsafe_access_error(); + uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4; + return true; + } + } + } + + else { // thread->thread_state() != _thread_in_Java + if (sig == SIGILL && VM_Version::is_determine_features_test_running()) { + // SIGILL must be caused by VM_Version::determine_features(). + *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL, + // flushing of icache is not necessary. + stub = pc + 4; // continue with next instruction. + } + else if (thread->thread_state() == _thread_in_vm && + sig == SIGBUS && thread->doing_unsafe_access()) { + // We don't really need a stub here! Just set the pending exeption and + // continue at the next instruction after the faulting read. Returning + // garbage from this read is ok. + thread->set_pending_unsafe_access_error(); + uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4; + return true; + } + } + + // Check to see if we caught the safepoint code in the + // process of write protecting the memory serialization page. + // It write enables the page immediately after protecting it + // so we can just return to retry the write. + if ((sig == SIGSEGV) && + // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see comment above). + // Use is_memory_serialization instead of si_addr. + ((NativeInstruction*)pc)->is_memory_serialization(thread, ucVoid)) { + // Synchronization problem in the pseudo memory barrier code (bug id 6546278) + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return true; + } + } + + if (stub != NULL) { + // Save all thread context in case we need to restore it. + if (thread != NULL) thread->set_saved_exception_pc(pc); + uc->uc_mcontext.regs->nip = (unsigned long)stub; + return true; + } + + // signal-chaining + if (os::Linux::chained_handler(sig, info, ucVoid)) { + return true; + } + + if (!abort_if_unrecognized) { + // caller wants another chance, so give it to him + return false; + } + + if (pc == NULL && uc != NULL) { + pc = os::Linux::ucontext_get_pc(uc); + } + +report_and_die: + // unmask current signal + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + sigprocmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(t, sig, pc, info, ucVoid); + err.report_and_die(); + + ShouldNotReachHere(); + return false; +} + +void os::Linux::init_thread_fpu_state(void) { + // Disable FP exceptions. + __asm__ __volatile__ ("mtfsfi 6,0"); +} + +int os::Linux::get_fpu_control_word(void) { + // x86 has problems with FPU precision after pthread_cond_timedwait(). + // nothing to do on ppc64. + return 0; +} + +void os::Linux::set_fpu_control_word(int fpu_control) { + // x86 has problems with FPU precision after pthread_cond_timedwait(). + // nothing to do on ppc64. +} + +//////////////////////////////////////////////////////////////////////////////// +// thread stack + +size_t os::Linux::min_stack_allowed = 768*K; + +bool os::Linux::supports_variable_stack_size() { return true; } + +// return default stack size for thr_type +size_t os::Linux::default_stack_size(os::ThreadType thr_type) { + // default stack size (compiler thread needs larger stack) + // Notice that the setting for compiler threads here have no impact + // because of the strange 'fallback logic' in os::create_thread(). + // Better set CompilerThreadStackSize in globals_.hpp if you want to + // specify a different stack size for compiler threads! + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K); + return s; +} + +size_t os::Linux::default_guard_size(os::ThreadType thr_type) { + return 2 * page_size(); +} + +// Java thread: +// +// Low memory addresses +// +------------------------+ +// | |\ JavaThread created by VM does not have glibc +// | glibc guard page | - guard, attached Java thread usually has +// | |/ 1 page glibc guard. +// P1 +------------------------+ Thread::stack_base() - Thread::stack_size() +// | |\ +// | HotSpot Guard Pages | - red and yellow pages +// | |/ +// +------------------------+ JavaThread::stack_yellow_zone_base() +// | |\ +// | Normal Stack | - +// | |/ +// P2 +------------------------+ Thread::stack_base() +// +// Non-Java thread: +// +// Low memory addresses +// +------------------------+ +// | |\ +// | glibc guard page | - usually 1 page +// | |/ +// P1 +------------------------+ Thread::stack_base() - Thread::stack_size() +// | |\ +// | Normal Stack | - +// | |/ +// P2 +------------------------+ Thread::stack_base() +// +// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from +// pthread_attr_getstack() + +static void current_stack_region(address * bottom, size_t * size) { + if (os::Linux::is_initial_thread()) { + // initial thread needs special handling because pthread_getattr_np() + // may return bogus value. + *bottom = os::Linux::initial_thread_stack_bottom(); + *size = os::Linux::initial_thread_stack_size(); + } else { + pthread_attr_t attr; + + int rslt = pthread_getattr_np(pthread_self(), &attr); + + // JVM needs to know exact stack location, abort if it fails + if (rslt != 0) { + if (rslt == ENOMEM) { + vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np"); + } else { + fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); + } + } + + if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) { + fatal("Can not locate current stack attributes!"); + } + + pthread_attr_destroy(&attr); + + } + assert(os::current_stack_pointer() >= *bottom && + os::current_stack_pointer() < *bottom + *size, "just checking"); +} + +address os::current_stack_base() { + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return (bottom + size); +} + +size_t os::current_stack_size() { + // stack size includes normal stack and HotSpot guard pages + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return size; +} + +///////////////////////////////////////////////////////////////////////////// +// helper functions for fatal error handler + +void os::print_context(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t* uc = (ucontext_t*)context; + + st->print_cr("Registers:"); + st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.regs->nip); + st->print("lr =" INTPTR_FORMAT " ", uc->uc_mcontext.regs->link); + st->print("ctr=" INTPTR_FORMAT " ", uc->uc_mcontext.regs->ctr); + st->cr(); + for (int i = 0; i < 32; i++) { + st->print("r%-2d=" INTPTR_FORMAT " ", i, uc->uc_mcontext.regs->gpr[i]); + if (i % 3 == 2) st->cr(); + } + st->cr(); + st->cr(); + + intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc); + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); + print_hex_dump(st, (address)sp, (address)(sp + 128), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::Linux::ucontext_get_pc(uc); + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); + print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4); + st->cr(); +} + +void os::print_register_info(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t *uc = (ucontext_t*)context; + + st->print_cr("Register to memory mapping:"); + st->cr(); + + // this is only for the "general purpose" registers + for (int i = 0; i < 32; i++) { + st->print("r%-2d=", i); + print_location(st, uc->uc_mcontext.regs->gpr[i]); + } + st->cr(); +} + +extern "C" { + int SpinPause() { + return 0; + } +} + +#ifndef PRODUCT +void os::verify_stack_alignment() { + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); +} +#endif diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.hpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.hpp new file mode 100644 index 00000000000..26bfc14273e --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_OS_LINUX_PPC_HPP +#define OS_CPU_LINUX_PPC_VM_OS_LINUX_PPC_HPP + + static void setup_fpu() {} + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + +#endif // OS_CPU_LINUX_PPC_VM_OS_LINUX_PPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp new file mode 100644 index 00000000000..c14df6ef9d3 --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_PREFETCH_LINUX_PPC_INLINE_HPP +#define OS_CPU_LINUX_PPC_VM_PREFETCH_LINUX_PPC_INLINE_HPP + +#include "runtime/prefetch.hpp" + + +inline void Prefetch::read(void *loc, intx interval) { + __asm__ __volatile__ ( + " dcbt 0, %0 \n" + : + : /*%0*/"r" ( ((address)loc) +((long)interval) ) + //: + ); +} + +inline void Prefetch::write(void *loc, intx interval) { + __asm__ __volatile__ ( + " dcbtst 0, %0 \n" + : + : /*%0*/"r" ( ((address)loc) +((long)interval) ) + //: + ); +} + +#endif // OS_CPU_LINUX_PPC_VM_PREFETCH_LINUX_OJDKPPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.cpp new file mode 100644 index 00000000000..8b6aa99f89d --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/threadLocalStorage.hpp" + +void ThreadLocalStorage::generate_code_for_get_thread() { + // nothing we can do here for user-level thread +} + +void ThreadLocalStorage::pd_init() { + // Nothing to do +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} diff --git a/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.hpp b/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.hpp new file mode 100644 index 00000000000..ac9beffcc85 --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/threadLS_linux_ppc.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_THREADLS_LINUX_PPC_HPP +#define OS_CPU_LINUX_PPC_VM_THREADLS_LINUX_PPC_HPP + + // Processor dependent parts of ThreadLocalStorage + +public: + static Thread* thread() { + return (Thread *) os::thread_local_storage_at(thread_index()); + } + +#endif // OS_CPU_LINUX_PPC_VM_THREADLS_LINUX_PPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp new file mode 100644 index 00000000000..77bfacd390c --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/frame.inline.hpp" +#include "thread_linux.inline.hpp" + +// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Linux/PPC. +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { + Unimplemented(); + return false; +} + +void JavaThread::cache_global_variables() { } diff --git a/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.hpp b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.hpp new file mode 100644 index 00000000000..237070ec1fe --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_THREAD_LINUX_PPC_HPP +#define OS_CPU_LINUX_PPC_VM_THREAD_LINUX_PPC_HPP + + private: + + void pd_initialize() { + _anchor.clear(); + _last_interpreter_fp = NULL; + } + + // The `last' frame is the youngest Java frame on the thread's stack. + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + + intptr_t* sp = last_Java_sp(); + address pc = _anchor.last_Java_pc(); + + // Last_Java_pc ist not set, if we come here from compiled code. + if (pc == NULL) { + pc = (address) *(sp + 2); + } + + return frame(sp, pc); + } + + public: + + void set_base_of_stack_pointer(intptr_t* base_sp) {} + intptr_t* base_of_stack_pointer() { return NULL; } + void record_base_of_stack_pointer() {} + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava); + + protected: + + // -Xprof support + // + // In order to find the last Java fp from an async profile + // tick, we store the current interpreter fp in the thread. + // This value is only valid while we are in the C++ interpreter + // and profiling. + intptr_t *_last_interpreter_fp; + + public: + + static ByteSize last_interpreter_fp_offset() { + return byte_offset_of(JavaThread, _last_interpreter_fp); + } + + intptr_t* last_interpreter_fp() { return _last_interpreter_fp; } + +#endif // OS_CPU_LINUX_PPC_VM_THREAD_LINUX_PPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/vmStructs_linux_ppc.hpp b/hotspot/src/os_cpu/linux_ppc/vm/vmStructs_linux_ppc.hpp new file mode 100644 index 00000000000..d947186ec86 --- /dev/null +++ b/hotspot/src/os_cpu/linux_ppc/vm/vmStructs_linux_ppc.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_LINUX_PPC_VM_VMSTRUCTS_LINUX_PPC_HPP +#define OS_CPU_LINUX_PPC_VM_VMSTRUCTS_LINUX_PPC_HPP + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + nonstatic_field(OSThread, _thread_id, pid_t) \ + nonstatic_field(OSThread, _pthread_id, pthread_t) + + +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ + \ + /**********************/ \ + /* Posix Thread IDs */ \ + /**********************/ \ + \ + declare_integer_type(pid_t) \ + declare_unsigned_integer_type(pthread_t) + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // OS_CPU_LINUX_PPC_VM_VMSTRUCTS_LINUX_PPC_HPP diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 77892878c63..4adc6df423b 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3614,7 +3614,7 @@ class CommandLineFlags { NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \ "Address to allocate shared memory region for class data") \ \ - diagnostic(bool, EnableInvokeDynamic, true PPC64_ONLY(&& false), \ + diagnostic(bool, EnableInvokeDynamic, true, \ "support JSR 292 (method handles, invokedynamic, " \ "anonymous classes") \ \ From a72b868ac2c41c310b301c71cf08c9a788cba7a7 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 26 Jul 2013 00:59:18 +0200 Subject: [PATCH 015/265] 8020775: PPC64 (part 12): posix signal printing Implement methods printing posix signal information and call them in unix os files. Reviewed-by: kvn, dholmes, twisti --- hotspot/src/os/bsd/vm/os_bsd.cpp | 58 +-- hotspot/src/os/linux/vm/os_linux.cpp | 58 +-- hotspot/src/os/posix/vm/os_posix.cpp | 532 ++++++++++++++++++++++- hotspot/src/os/posix/vm/os_posix.hpp | 26 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 58 +-- 5 files changed, 555 insertions(+), 177 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index c5d15f20d6e..4c1cb78b791 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1618,58 +1618,12 @@ void os::print_memory_info(outputStream* st) { st->cr(); } -// Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific -// but they're the same for all the bsd arch that we support -// and they're the same for solaris but there's no common place to put this. -const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", - "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", - "ILL_COPROC", "ILL_BADSTK" }; - -const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", - "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", - "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; - -const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; - -const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; - void os::print_siginfo(outputStream* st, void* siginfo) { - st->print("siginfo:"); + const siginfo_t* si = (const siginfo_t*)siginfo; - const int buflen = 100; - char buf[buflen]; - siginfo_t *si = (siginfo_t*)siginfo; - st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); - if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { - st->print("si_errno=%s", buf); - } else { - st->print("si_errno=%d", si->si_errno); - } - const int c = si->si_code; - assert(c > 0, "unexpected si_code"); - switch (si->si_signo) { - case SIGILL: - st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGFPE: - st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGSEGV: - st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGBUS: - st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - default: - st->print(", si_code=%d", si->si_code); - // no si_addr - } + os::Posix::print_siginfo_brief(st, si); - if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && + if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && UseSharedSpaces) { FileMapInfo* mapinfo = FileMapInfo::current_info(); if (mapinfo->is_in_shared_space(si->si_addr)) { @@ -3338,7 +3292,8 @@ static void print_signal_handler(outputStream* st, int sig, st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); } - st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); + st->print(", sa_mask[0]="); + os::Posix::print_signal_set_short(st, &sa.sa_mask); address rh = VMError::get_resetted_sighandler(sig); // May be, handler was resetted by VMError? @@ -3347,7 +3302,8 @@ static void print_signal_handler(outputStream* st, int sig, sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; } - st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); + st->print(", sa_flags="); + os::Posix::print_sa_flags(st, sa.sa_flags); // Check: is it our handler? if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 2237313d02e..01c01c4208b 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2231,58 +2231,12 @@ void os::pd_print_cpu_info(outputStream* st) { st->cr(); } -// Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific -// but they're the same for all the linux arch that we support -// and they're the same for solaris but there's no common place to put this. -const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", - "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", - "ILL_COPROC", "ILL_BADSTK" }; - -const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", - "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", - "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; - -const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; - -const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; - void os::print_siginfo(outputStream* st, void* siginfo) { - st->print("siginfo:"); + const siginfo_t* si = (const siginfo_t*)siginfo; - const int buflen = 100; - char buf[buflen]; - siginfo_t *si = (siginfo_t*)siginfo; - st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); - if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { - st->print("si_errno=%s", buf); - } else { - st->print("si_errno=%d", si->si_errno); - } - const int c = si->si_code; - assert(c > 0, "unexpected si_code"); - switch (si->si_signo) { - case SIGILL: - st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGFPE: - st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGSEGV: - st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGBUS: - st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - default: - st->print(", si_code=%d", si->si_code); - // no si_addr - } + os::Posix::print_siginfo_brief(st, si); - if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && + if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && UseSharedSpaces) { FileMapInfo* mapinfo = FileMapInfo::current_info(); if (mapinfo->is_in_shared_space(si->si_addr)) { @@ -4278,7 +4232,8 @@ static void print_signal_handler(outputStream* st, int sig, st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); } - st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); + st->print(", sa_mask[0]="); + os::Posix::print_signal_set_short(st, &sa.sa_mask); address rh = VMError::get_resetted_sighandler(sig); // May be, handler was resetted by VMError? @@ -4287,7 +4242,8 @@ static void print_signal_handler(outputStream* st, int sig, sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; } - st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); + st->print(", sa_flags="); + os::Posix::print_sa_flags(st, sa.sa_flags); // Check: is it our handler? if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index bf6a1fafacd..61b8116f2f6 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1,36 +1,44 @@ /* -* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. -* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -* -* This code is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License version 2 only, as -* published by the Free Software Foundation. -* -* This code is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -* version 2 for more details (a copy is included in the LICENSE file that -* accompanied this code). -* -* You should have received a copy of the GNU General Public License version -* 2 along with this work; if not, write to the Free Software Foundation, -* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -* -* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -* or visit www.oracle.com if you need additional information or have any -* questions. -* -*/ + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "utilities/globalDefinitions.hpp" #include "prims/jvm.h" #include "runtime/frame.inline.hpp" #include "runtime/os.hpp" #include "utilities/vmError.hpp" +#include #include #include #include +// Todo: provide a os::get_max_process_id() or similar. Number of processes +// may have been configured, can be read more accurately from proc fs etc. +#ifndef MAX_PID +#define MAX_PID INT_MAX +#endif +#define IS_VALID_PID(p) (p > 0 && p < MAX_PID) // Check core dump limit and report possible place where core can be found void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { @@ -156,7 +164,7 @@ void os::Posix::print_rlimit_info(outputStream* st) { if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); else st->print("%uk", rlim.rlim_cur >> 10); - //Isn't there on solaris + // Isn't there on solaris #ifndef TARGET_OS_FAMILY_solaris st->print(", NPROC "); getrlimit(RLIMIT_NPROC, &rlim); @@ -260,6 +268,484 @@ FILE* os::open(int fd, const char* mode) { return ::fdopen(fd, mode); } + +// Returned string is a constant. For unknown signals "UNKNOWN" is returned. +const char* os::Posix::get_signal_name(int sig, char* out, size_t outlen) { + + static const struct { + int sig; const char* name; + } + info[] = + { + { SIGABRT, "SIGABRT" }, +#ifdef SIGAIO + { SIGAIO, "SIGAIO" }, +#endif + { SIGALRM, "SIGALRM" }, +#ifdef SIGALRM1 + { SIGALRM1, "SIGALRM1" }, +#endif + { SIGBUS, "SIGBUS" }, +#ifdef SIGCANCEL + { SIGCANCEL, "SIGCANCEL" }, +#endif + { SIGCHLD, "SIGCHLD" }, +#ifdef SIGCLD + { SIGCLD, "SIGCLD" }, +#endif + { SIGCONT, "SIGCONT" }, +#ifdef SIGCPUFAIL + { SIGCPUFAIL, "SIGCPUFAIL" }, +#endif +#ifdef SIGDANGER + { SIGDANGER, "SIGDANGER" }, +#endif +#ifdef SIGDIL + { SIGDIL, "SIGDIL" }, +#endif +#ifdef SIGEMT + { SIGEMT, "SIGEMT" }, +#endif + { SIGFPE, "SIGFPE" }, +#ifdef SIGFREEZE + { SIGFREEZE, "SIGFREEZE" }, +#endif +#ifdef SIGGFAULT + { SIGGFAULT, "SIGGFAULT" }, +#endif +#ifdef SIGGRANT + { SIGGRANT, "SIGGRANT" }, +#endif + { SIGHUP, "SIGHUP" }, + { SIGILL, "SIGILL" }, + { SIGINT, "SIGINT" }, +#ifdef SIGIO + { SIGIO, "SIGIO" }, +#endif +#ifdef SIGIOINT + { SIGIOINT, "SIGIOINT" }, +#endif +#ifdef SIGIOT + // SIGIOT is there for BSD compatibility, but on most Unices just a + // synonym for SIGABRT. The result should be "SIGABRT", not + // "SIGIOT". + #if (SIGIOT != SIGABRT ) + { SIGIOT, "SIGIOT" }, + #endif +#endif +#ifdef SIGKAP + { SIGKAP, "SIGKAP" }, +#endif + { SIGKILL, "SIGKILL" }, +#ifdef SIGLOST + { SIGLOST, "SIGLOST" }, +#endif +#ifdef SIGLWP + { SIGLWP, "SIGLWP" }, +#endif +#ifdef SIGLWPTIMER + { SIGLWPTIMER, "SIGLWPTIMER" }, +#endif +#ifdef SIGMIGRATE + { SIGMIGRATE, "SIGMIGRATE" }, +#endif +#ifdef SIGMSG + { SIGMSG, "SIGMSG" }, +#endif + { SIGPIPE, "SIGPIPE" }, +#ifdef SIGPOLL + { SIGPOLL, "SIGPOLL" }, +#endif +#ifdef SIGPRE + { SIGPRE, "SIGPRE" }, +#endif + { SIGPROF, "SIGPROF" }, +#ifdef SIGPTY + { SIGPTY, "SIGPTY" }, +#endif +#ifdef SIGPWR + { SIGPWR, "SIGPWR" }, +#endif + { SIGQUIT, "SIGQUIT" }, +#ifdef SIGRECONFIG + { SIGRECONFIG, "SIGRECONFIG" }, +#endif +#ifdef SIGRECOVERY + { SIGRECOVERY, "SIGRECOVERY" }, +#endif +#ifdef SIGRESERVE + { SIGRESERVE, "SIGRESERVE" }, +#endif +#ifdef SIGRETRACT + { SIGRETRACT, "SIGRETRACT" }, +#endif +#ifdef SIGSAK + { SIGSAK, "SIGSAK" }, +#endif + { SIGSEGV, "SIGSEGV" }, +#ifdef SIGSOUND + { SIGSOUND, "SIGSOUND" }, +#endif + { SIGSTOP, "SIGSTOP" }, + { SIGSYS, "SIGSYS" }, +#ifdef SIGSYSERROR + { SIGSYSERROR, "SIGSYSERROR" }, +#endif +#ifdef SIGTALRM + { SIGTALRM, "SIGTALRM" }, +#endif + { SIGTERM, "SIGTERM" }, +#ifdef SIGTHAW + { SIGTHAW, "SIGTHAW" }, +#endif + { SIGTRAP, "SIGTRAP" }, +#ifdef SIGTSTP + { SIGTSTP, "SIGTSTP" }, +#endif + { SIGTTIN, "SIGTTIN" }, + { SIGTTOU, "SIGTTOU" }, +#ifdef SIGURG + { SIGURG, "SIGURG" }, +#endif + { SIGUSR1, "SIGUSR1" }, + { SIGUSR2, "SIGUSR2" }, +#ifdef SIGVIRT + { SIGVIRT, "SIGVIRT" }, +#endif + { SIGVTALRM, "SIGVTALRM" }, +#ifdef SIGWAITING + { SIGWAITING, "SIGWAITING" }, +#endif +#ifdef SIGWINCH + { SIGWINCH, "SIGWINCH" }, +#endif +#ifdef SIGWINDOW + { SIGWINDOW, "SIGWINDOW" }, +#endif + { SIGXCPU, "SIGXCPU" }, + { SIGXFSZ, "SIGXFSZ" }, +#ifdef SIGXRES + { SIGXRES, "SIGXRES" }, +#endif + { -1, NULL } + }; + + const char* ret = NULL; + +#ifdef SIGRTMIN + if (sig >= SIGRTMIN && sig <= SIGRTMAX) { + if (sig == SIGRTMIN) { + ret = "SIGRTMIN"; + } else if (sig == SIGRTMAX) { + ret = "SIGRTMAX"; + } else { + jio_snprintf(out, outlen, "SIGRTMIN+%d", sig - SIGRTMIN); + return out; + } + } +#endif + + if (sig > 0) { + for (int idx = 0; info[idx].sig != -1; idx ++) { + if (info[idx].sig == sig) { + ret = info[idx].name; + break; + } + } + } + + if (!ret) { + if (!is_valid_signal(sig)) { + ret = "INVALID"; + } else { + ret = "UNKNOWN"; + } + } + + jio_snprintf(out, outlen, ret); + return out; +} + +// Returns true if signal number is valid. +bool os::Posix::is_valid_signal(int sig) { + // MacOS not really POSIX compliant: sigaddset does not return + // an error for invalid signal numbers. However, MacOS does not + // support real time signals and simply seems to have just 33 + // signals with no holes in the signal range. +#ifdef __APPLE__ + return sig >= 1 && sig < NSIG; +#else + // Use sigaddset to check for signal validity. + sigset_t set; + if (sigaddset(&set, sig) == -1 && errno == EINVAL) { + return false; + } + return true; +#endif +} + +#define NUM_IMPORTANT_SIGS 32 +// Returns one-line short description of a signal set in a user provided buffer. +const char* os::Posix::describe_signal_set_short(const sigset_t* set, char* buffer, size_t buf_size) { + assert(buf_size = (NUM_IMPORTANT_SIGS + 1), "wrong buffer size"); + // Note: for shortness, just print out the first 32. That should + // cover most of the useful ones, apart from realtime signals. + for (int sig = 1; sig <= NUM_IMPORTANT_SIGS; sig++) { + const int rc = sigismember(set, sig); + if (rc == -1 && errno == EINVAL) { + buffer[sig-1] = '?'; + } else { + buffer[sig-1] = rc == 0 ? '0' : '1'; + } + } + buffer[NUM_IMPORTANT_SIGS] = 0; + return buffer; +} + +// Prints one-line description of a signal set. +void os::Posix::print_signal_set_short(outputStream* st, const sigset_t* set) { + char buf[NUM_IMPORTANT_SIGS + 1]; + os::Posix::describe_signal_set_short(set, buf, sizeof(buf)); + st->print(buf); +} + +// Writes one-line description of a combination of sigaction.sa_flags into a user +// provided buffer. Returns that buffer. +const char* os::Posix::describe_sa_flags(int flags, char* buffer, size_t size) { + char* p = buffer; + size_t remaining = size; + bool first = true; + int idx = 0; + + assert(buffer, "invalid argument"); + + if (size == 0) { + return buffer; + } + + strncpy(buffer, "none", size); + + const struct { + int i; + const char* s; + } flaginfo [] = { + { SA_NOCLDSTOP, "SA_NOCLDSTOP" }, + { SA_ONSTACK, "SA_ONSTACK" }, + { SA_RESETHAND, "SA_RESETHAND" }, + { SA_RESTART, "SA_RESTART" }, + { SA_SIGINFO, "SA_SIGINFO" }, + { SA_NOCLDWAIT, "SA_NOCLDWAIT" }, + { SA_NODEFER, "SA_NODEFER" }, +#ifdef AIX + { SA_ONSTACK, "SA_ONSTACK" }, + { SA_OLDSTYLE, "SA_OLDSTYLE" }, +#endif + { 0, NULL } + }; + + for (idx = 0; flaginfo[idx].s && remaining > 1; idx++) { + if (flags & flaginfo[idx].i) { + if (first) { + jio_snprintf(p, remaining, "%s", flaginfo[idx].s); + first = false; + } else { + jio_snprintf(p, remaining, "|%s", flaginfo[idx].s); + } + const size_t len = strlen(p); + p += len; + remaining -= len; + } + } + + buffer[size - 1] = '\0'; + + return buffer; +} + +// Prints one-line description of a combination of sigaction.sa_flags. +void os::Posix::print_sa_flags(outputStream* st, int flags) { + char buffer[0x100]; + os::Posix::describe_sa_flags(flags, buffer, sizeof(buffer)); + st->print(buffer); +} + +// Helper function for os::Posix::print_siginfo_...(): +// return a textual description for signal code. +struct enum_sigcode_desc_t { + const char* s_name; + const char* s_desc; +}; + +static bool get_signal_code_description(const siginfo_t* si, enum_sigcode_desc_t* out) { + + const struct { + int sig; int code; const char* s_code; const char* s_desc; + } t1 [] = { + { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode." }, + { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand." }, + { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode." }, + { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap." }, + { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode." }, + { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register." }, + { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error." }, + { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error." }, +#if defined(IA64) && defined(LINUX) + { SIGILL, ILL_BADIADDR, "ILL_BADIADDR", "Unimplemented instruction address" }, + { SIGILL, ILL_BREAK, "ILL_BREAK", "Application Break instruction" }, +#endif + { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero." }, + { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow." }, + { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating-point divide by zero." }, + { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating-point overflow." }, + { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating-point underflow." }, + { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating-point inexact result." }, + { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating-point operation." }, + { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range." }, + { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object." }, + { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for mapped object." }, +#ifdef AIX + // no explanation found what keyerr would be + { SIGSEGV, SEGV_KEYERR, "SEGV_KEYERR", "key error" }, +#endif +#if defined(IA64) && !defined(AIX) + { SIGSEGV, SEGV_PSTKOVF, "SEGV_PSTKOVF", "Paragraph stack overflow" }, +#endif + { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment." }, + { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Nonexistent physical address." }, + { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object-specific hardware error." }, + { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint." }, + { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap." }, + { SIGCHLD, CLD_EXITED, "CLD_EXITED", "Child has exited." }, + { SIGCHLD, CLD_KILLED, "CLD_KILLED", "Child has terminated abnormally and did not create a core file." }, + { SIGCHLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally and created a core file." }, + { SIGCHLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped." }, + { SIGCHLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped." }, + { SIGCHLD, CLD_CONTINUED,"CLD_CONTINUED","Stopped child has continued." }, +#ifdef SIGPOLL + { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available." }, + { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available." }, + { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error." }, + { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available." }, + { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected. [Option End]" }, +#endif + { -1, -1, NULL, NULL } + }; + + // Codes valid in any signal context. + const struct { + int code; const char* s_code; const char* s_desc; + } t2 [] = { + { SI_USER, "SI_USER", "Signal sent by kill()." }, + { SI_QUEUE, "SI_QUEUE", "Signal sent by the sigqueue()." }, + { SI_TIMER, "SI_TIMER", "Signal generated by expiration of a timer set by timer_settime()." }, + { SI_ASYNCIO, "SI_ASYNCIO", "Signal generated by completion of an asynchronous I/O request." }, + { SI_MESGQ, "SI_MESGQ", "Signal generated by arrival of a message on an empty message queue." }, + // Linux specific +#ifdef SI_TKILL + { SI_TKILL, "SI_TKILL", "Signal sent by tkill (pthread_kill)" }, +#endif +#ifdef SI_DETHREAD + { SI_DETHREAD, "SI_DETHREAD", "Signal sent by execve() killing subsidiary threads" }, +#endif +#ifdef SI_KERNEL + { SI_KERNEL, "SI_KERNEL", "Signal sent by kernel." }, +#endif +#ifdef SI_SIGIO + { SI_SIGIO, "SI_SIGIO", "Signal sent by queued SIGIO" }, +#endif + +#ifdef AIX + { SI_UNDEFINED, "SI_UNDEFINED","siginfo contains partial information" }, + { SI_EMPTY, "SI_EMPTY", "siginfo contains no useful information" }, +#endif + +#ifdef __sun + { SI_NOINFO, "SI_NOINFO", "No signal information" }, + { SI_RCTL, "SI_RCTL", "kernel generated signal via rctl action" }, + { SI_LWP, "SI_LWP", "Signal sent via lwp_kill" }, +#endif + + { -1, NULL, NULL } + }; + + const char* s_code = NULL; + const char* s_desc = NULL; + + for (int i = 0; t1[i].sig != -1; i ++) { + if (t1[i].sig == si->si_signo && t1[i].code == si->si_code) { + s_code = t1[i].s_code; + s_desc = t1[i].s_desc; + break; + } + } + + if (s_code == NULL) { + for (int i = 0; t2[i].s_code != NULL; i ++) { + if (t2[i].code == si->si_code) { + s_code = t2[i].s_code; + s_desc = t2[i].s_desc; + } + } + } + + if (s_code == NULL) { + out->s_name = "unknown"; + out->s_desc = "unknown"; + return false; + } + + out->s_name = s_code; + out->s_desc = s_desc; + + return true; +} + +// A POSIX conform, platform-independend siginfo print routine. +// Short print out on one line. +void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) { + char buf[20]; + os->print("siginfo: "); + + if (!si) { + os->print(""); + return; + } + + // See print_siginfo_full() for details. + const int sig = si->si_signo; + + os->print("si_signo: %d (%s)", sig, os::Posix::get_signal_name(sig, buf, sizeof(buf))); + + enum_sigcode_desc_t ed; + if (get_signal_code_description(si, &ed)) { + os->print(", si_code: %d (%s)", si->si_code, ed.s_name); + } else { + os->print(", si_code: %d (unknown)", si->si_code); + } + + if (si->si_errno) { + os->print(", si_errno: %d", si->si_errno); + } + + const int me = (int) ::getpid(); + const int pid = (int) si->si_pid; + + if (si->si_code == SI_USER || si->si_code == SI_QUEUE) { + if (IS_VALID_PID(pid) && pid != me) { + os->print(", sent from pid: %d (uid: %d)", pid, (int) si->si_uid); + } + } else if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || + sig == SIGTRAP || sig == SIGFPE) { + os->print(", si_addr: " PTR_FORMAT, si->si_addr); +#ifdef SIGPOLL + } else if (sig == SIGPOLL) { + os->print(", si_band: " PTR64_FORMAT, (uint64_t)si->si_band); +#endif + } else if (sig == SIGCHLD) { + os->print_cr(", si_pid: %d, si_uid: %d, si_status: %d", (int) si->si_pid, si->si_uid, si->si_status); + } +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); } diff --git a/hotspot/src/os/posix/vm/os_posix.hpp b/hotspot/src/os/posix/vm/os_posix.hpp index 16a065acf30..debb0f4ee2f 100644 --- a/hotspot/src/os/posix/vm/os_posix.hpp +++ b/hotspot/src/os/posix/vm/os_posix.hpp @@ -34,6 +34,30 @@ protected: static void print_libversion_info(outputStream* st); static void print_load_average(outputStream* st); +public: + + // Returns true if signal is valid. + static bool is_valid_signal(int sig); + + // Helper function, returns a string (e.g. "SIGILL") for a signal. + // Returned string is a constant. For unknown signals "UNKNOWN" is returned. + static const char* get_signal_name(int sig, char* out, size_t outlen); + + // Returns one-line short description of a signal set in a user provided buffer. + static const char* describe_signal_set_short(const sigset_t* set, char* buffer, size_t size); + + // Prints a short one-line description of a signal set. + static void print_signal_set_short(outputStream* st, const sigset_t* set); + + // Writes a one-line description of a combination of sigaction.sa_flags + // into a user provided buffer. Returns that buffer. + static const char* describe_sa_flags(int flags, char* buffer, size_t size); + + // Prints a one-line description of a combination of sigaction.sa_flags. + static void print_sa_flags(outputStream* st, int flags); + + // A POSIX conform, platform-independend siginfo print routine. + static void print_siginfo_brief(outputStream* os, const siginfo_t* si); }; @@ -57,4 +81,4 @@ private: sigjmp_buf _jmpbuf; }; -#endif +#endif // OS_POSIX_VM_OS_POSIX_HPP diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 0a94cb536ab..1706b45c63a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2247,58 +2247,12 @@ void os::print_memory_info(outputStream* st) { (void) check_addr0(st); } -// Taken from /usr/include/sys/machsig.h Supposed to be architecture specific -// but they're the same for all the solaris architectures that we support. -const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", - "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", - "ILL_COPROC", "ILL_BADSTK" }; - -const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", - "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", - "FPE_FLTINV", "FPE_FLTSUB" }; - -const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; - -const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; - void os::print_siginfo(outputStream* st, void* siginfo) { - st->print("siginfo:"); + const siginfo_t* si = (const siginfo_t*)siginfo; - const int buflen = 100; - char buf[buflen]; - siginfo_t *si = (siginfo_t*)siginfo; - st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); - char *err = strerror(si->si_errno); - if (si->si_errno != 0 && err != NULL) { - st->print("si_errno=%s", err); - } else { - st->print("si_errno=%d", si->si_errno); - } - const int c = si->si_code; - assert(c > 0, "unexpected si_code"); - switch (si->si_signo) { - case SIGILL: - st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGFPE: - st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGSEGV: - st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGBUS: - st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - default: - st->print(", si_code=%d", si->si_code); - // no si_addr - } + os::Posix::print_siginfo_brief(st, si); - if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && + if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && UseSharedSpaces) { FileMapInfo* mapinfo = FileMapInfo::current_info(); if (mapinfo->is_in_shared_space(si->si_addr)) { @@ -2368,7 +2322,8 @@ static void print_signal_handler(outputStream* st, int sig, st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); } - st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); + st->print(", sa_mask[0]="); + os::Posix::print_signal_set_short(st, &sa.sa_mask); address rh = VMError::get_resetted_sighandler(sig); // May be, handler was resetted by VMError? @@ -2377,7 +2332,8 @@ static void print_signal_handler(outputStream* st, int sig, sa.sa_flags = VMError::get_resetted_sigflags(sig); } - st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); + st->print(", sa_flags="); + os::Posix::print_sa_flags(st, sa.sa_flags); // Check: is it our handler? if(handler == CAST_FROM_FN_PTR(address, signalHandler) || From fac7ee02c53df02d7161ecb9fe81c42479145215 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 22 Aug 2013 09:39:54 -0700 Subject: [PATCH 016/265] 8023033: PPC64 (part 13): basic changes for AIX Added AIX includes alpha-sorted before BSD. Fix compilation issues with xlC in shared code. Basic shared platform dependend adaption (vm_version etc.). Reviewed-by: kvn, dholmes, stefank --- hotspot/src/os/posix/vm/os_posix.cpp | 4 ++-- hotspot/src/share/vm/c1/c1_globals.hpp | 3 +++ hotspot/src/share/vm/classfile/classLoader.cpp | 3 +++ hotspot/src/share/vm/code/nmethod.cpp | 2 +- hotspot/src/share/vm/code/relocInfo.hpp | 4 ++-- hotspot/src/share/vm/code/stubs.hpp | 3 +++ hotspot/src/share/vm/code/vmreg.hpp | 8 ++++---- hotspot/src/share/vm/compiler/disassembler.hpp | 3 +++ .../concurrentMarkSweep/adaptiveFreeList.cpp | 2 +- .../concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp | 3 +++ .../parallelScavenge/parMarkBitMap.cpp | 3 +++ .../parallelScavenge/psVirtualspace.cpp | 3 +++ .../share/vm/interpreter/bytecodeInterpreter.cpp | 3 +++ hotspot/src/share/vm/libadt/port.hpp | 2 -- hotspot/src/share/vm/memory/allocation.cpp | 3 +++ hotspot/src/share/vm/memory/allocation.hpp | 5 ++++- hotspot/src/share/vm/memory/space.hpp | 3 +++ hotspot/src/share/vm/memory/universe.cpp | 7 ++++++- hotspot/src/share/vm/oops/typeArrayOop.hpp | 3 +++ hotspot/src/share/vm/opto/c2_globals.hpp | 3 +++ hotspot/src/share/vm/prims/jvm.cpp | 3 +++ hotspot/src/share/vm/prims/jvm.h | 3 +++ hotspot/src/share/vm/prims/nativeLookup.cpp | 3 +++ hotspot/src/share/vm/runtime/arguments.cpp | 3 +++ hotspot/src/share/vm/runtime/atomic.cpp | 3 +++ hotspot/src/share/vm/runtime/atomic.inline.hpp | 5 +++++ hotspot/src/share/vm/runtime/globals.hpp | 15 +++++++++++++++ hotspot/src/share/vm/runtime/interfaceSupport.hpp | 3 +++ hotspot/src/share/vm/runtime/javaFrameAnchor.hpp | 3 +++ hotspot/src/share/vm/runtime/mutexLocker.hpp | 3 +++ hotspot/src/share/vm/runtime/os.hpp | 11 +++++++++++ hotspot/src/share/vm/runtime/osThread.hpp | 3 +++ .../src/share/vm/runtime/sharedRuntimeTrans.cpp | 4 ++++ .../src/share/vm/runtime/sharedRuntimeTrig.cpp | 8 ++++---- hotspot/src/share/vm/runtime/thread.hpp | 3 +++ hotspot/src/share/vm/runtime/thread.inline.hpp | 3 +++ .../src/share/vm/runtime/threadLocalStorage.hpp | 3 +++ hotspot/src/share/vm/runtime/timer.cpp | 3 +++ hotspot/src/share/vm/runtime/virtualspace.cpp | 3 +++ hotspot/src/share/vm/runtime/vmStructs.cpp | 3 +++ hotspot/src/share/vm/runtime/vm_version.cpp | 4 ++++ hotspot/src/share/vm/utilities/accessFlags.cpp | 3 +++ hotspot/src/share/vm/utilities/bitMap.cpp | 3 +++ hotspot/src/share/vm/utilities/debug.hpp | 2 +- hotspot/src/share/vm/utilities/decoder.cpp | 4 ++++ .../src/share/vm/utilities/globalDefinitions.hpp | 3 +++ hotspot/src/share/vm/utilities/histogram.hpp | 3 +++ hotspot/src/share/vm/utilities/macros.hpp | 8 ++++++++ hotspot/src/share/vm/utilities/ostream.cpp | 5 ++++- hotspot/src/share/vm/utilities/resourceHash.hpp | 8 ++++++-- hotspot/src/share/vm/utilities/taskqueue.hpp | 3 +++ 51 files changed, 182 insertions(+), 22 deletions(-) diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 61b8116f2f6..66ca97ba1f8 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -165,7 +165,7 @@ void os::Posix::print_rlimit_info(outputStream* st) { else st->print("%uk", rlim.rlim_cur >> 10); // Isn't there on solaris -#ifndef TARGET_OS_FAMILY_solaris +#if! defined(TARGET_OS_FAMILY_solaris) && !defined(TARGET_OS_FAMILY_aix) st->print(", NPROC "); getrlimit(RLIMIT_NPROC, &rlim); if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); @@ -487,7 +487,7 @@ bool os::Posix::is_valid_signal(int sig) { #define NUM_IMPORTANT_SIGS 32 // Returns one-line short description of a signal set in a user provided buffer. const char* os::Posix::describe_signal_set_short(const sigset_t* set, char* buffer, size_t buf_size) { - assert(buf_size = (NUM_IMPORTANT_SIGS + 1), "wrong buffer size"); + assert(buf_size == (NUM_IMPORTANT_SIGS + 1), "wrong buffer size"); // Note: for shortness, just print out the first 32. That should // cover most of the useful ones, apart from realtime signals. for (int sig = 1; sig <= NUM_IMPORTANT_SIGS; sig++) { diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index 844880be256..49ef9145182 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c1_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "c1_globals_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "c1_globals_bsd.hpp" #endif diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 32a4da05bb5..942144f75a8 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -68,6 +68,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 1dfc3ba8f07..fb48d430058 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -799,7 +799,7 @@ nmethod::nmethod( } #endif // def HAVE_DTRACE_H -void* nmethod::operator new(size_t size, int nmethod_size) throw () { +void* nmethod::operator new(size_t size, int nmethod_size) { // Not critical, may return null if there is too little continuous memory return CodeCache::allocate(nmethod_size); } diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index 2b8611ca294..14fbc496de6 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.hpp @@ -365,7 +365,7 @@ class relocInfo VALUE_OBJ_CLASS_SPEC { // "immediate" in the prefix header word itself. This optimization // is invisible outside this module.) - inline friend relocInfo prefix_relocInfo(int datalen = 0); + inline friend relocInfo prefix_relocInfo(int datalen); protected: // an immediate relocInfo optimizes a prefix with one 10-bit unsigned value @@ -460,7 +460,7 @@ inline relocInfo filler_relocInfo() { return relocInfo(relocInfo::none, relocInfo::offset_limit() - relocInfo::offset_unit); } -inline relocInfo prefix_relocInfo(int datalen) { +inline relocInfo prefix_relocInfo(int datalen = 0) { assert(relocInfo::fits_into_immediate(datalen), "datalen in limits"); return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen); } diff --git a/hotspot/src/share/vm/code/stubs.hpp b/hotspot/src/share/vm/code/stubs.hpp index 233f43e2dae..25cd9ee011f 100644 --- a/hotspot/src/share/vm/code/stubs.hpp +++ b/hotspot/src/share/vm/code/stubs.hpp @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index dfb957ba535..1ef07ec199c 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -73,7 +73,7 @@ friend class OptoReg; // friend class Location; private: enum { - BAD = -1 + BAD_REG = -1 }; @@ -86,7 +86,7 @@ private: public: - static VMReg as_VMReg(int val, bool bad_ok = false) { assert(val > BAD || bad_ok, "invalid"); return (VMReg) (intptr_t) val; } + static VMReg as_VMReg(int val, bool bad_ok = false) { assert(val > BAD_REG || bad_ok, "invalid"); return (VMReg) (intptr_t) val; } const char* name() { if (is_reg()) { @@ -98,8 +98,8 @@ public: return "STACKED REG"; } } - static VMReg Bad() { return (VMReg) (intptr_t) BAD; } - bool is_valid() const { return ((intptr_t) this) != BAD; } + static VMReg Bad() { return (VMReg) (intptr_t) BAD_REG; } + bool is_valid() const { return ((intptr_t) this) != BAD_REG; } bool is_stack() const { return (intptr_t) this >= (intptr_t) stack0; } bool is_reg() const { return is_valid() && !is_stack(); } diff --git a/hotspot/src/share/vm/compiler/disassembler.hpp b/hotspot/src/share/vm/compiler/disassembler.hpp index c81666ec25d..c348ae65088 100644 --- a/hotspot/src/share/vm/compiler/disassembler.hpp +++ b/hotspot/src/share/vm/compiler/disassembler.hpp @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp index cfba2376ea8..37e079aa01f 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp @@ -122,7 +122,7 @@ void AdaptiveFreeList::return_chunk_at_head(Chunk* chunk, bool record_ret template void AdaptiveFreeList::return_chunk_at_tail(Chunk* chunk) { - return_chunk_at_tail(chunk, true); + AdaptiveFreeList::return_chunk_at_tail(chunk, true); } template diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp index d60fe806892..955039909ca 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp index 0db70cdd7d8..76a368b692c 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp @@ -38,6 +38,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp index 9999527302a..90672fba061 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index ba72cf4ec5d..b22ce9718db 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -67,6 +67,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "orderAccess_aix_ppc.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "orderAccess_bsd_x86.inline.hpp" #endif diff --git a/hotspot/src/share/vm/libadt/port.hpp b/hotspot/src/share/vm/libadt/port.hpp index ad7e77c1a9a..903e486a69e 100644 --- a/hotspot/src/share/vm/libadt/port.hpp +++ b/hotspot/src/share/vm/libadt/port.hpp @@ -91,8 +91,6 @@ inline int max( int a, int b) { return a > b ? a : b; } #define IMPLEMENTATION #include #include -inline int min( int a, int b) { return a < b ? a : b; } -inline int max( int a, int b) { return a > b ? a : b; } #elif defined(_MSC_VER) // Microsoft Visual C++ diff --git a/hotspot/src/share/vm/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp index 6a80c47385e..5230a459ef0 100644 --- a/hotspot/src/share/vm/memory/allocation.cpp +++ b/hotspot/src/share/vm/memory/allocation.cpp @@ -45,6 +45,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index aa916660d8b..316b8cdca61 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -220,8 +220,11 @@ template class CHeapObj ALLOCATION_SUPER_CLASS_SPEC { class StackObj ALLOCATION_SUPER_CLASS_SPEC { private: void* operator new(size_t size); - void operator delete(void* p); void* operator new [](size_t size); +#ifdef __IBMCPP__ + public: +#endif + void operator delete(void* p); void operator delete [](void* p); }; diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index eb1e209a850..3a22815c79e 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -45,6 +45,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 511610bd3bf..b60f22f523f 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -747,7 +747,7 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { // the correct no-access prefix. // The final value will be set in initialize_heap() below. Universe::set_narrow_oop_base((address)NarrowOopHeapMax); -#ifdef _WIN64 +#if defined(_WIN64) || defined(AIX) if (UseLargePages) { // Cannot allocate guard pages for implicit checks in indexed // addressing mode when large pages are specified on windows. @@ -825,6 +825,11 @@ jint Universe::initialize_heap() { // Can't reserve heap below 32Gb. // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); +#ifdef AIX + // There is no protected page before the heap. This assures all oops + // are decoded so that NULL is preserved, so this page will not be accessed. + Universe::set_narrow_oop_use_implicit_null_checks(false); +#endif if (verbose) { tty->print(", %s: "PTR_FORMAT, narrow_oop_mode_to_string(HeapBasedNarrowOop), diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index cee2b8a5e2d..29ad6cd5c84 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -51,6 +51,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "orderAccess_aix_ppc.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "orderAccess_bsd_x86.inline.hpp" #endif diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 1acbd0a036b..80f1e49c10f 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c2_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "c2_globals_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "c2_globals_bsd.hpp" #endif diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index caed2d13612..776337be354 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -76,6 +76,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "jvm_aix.h" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "jvm_bsd.h" #endif diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 6248f4d793d..0e2a27f1147 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "jvm_aix.h" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "jvm_bsd.h" #endif diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 990600eea27..c4cd3d8d236 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -50,6 +50,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 0662b6912b9..15165d629b7 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -49,6 +49,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/atomic.cpp b/hotspot/src/share/vm/runtime/atomic.cpp index 87c80ad3335..8572afab3d7 100644 --- a/hotspot/src/share/vm/runtime/atomic.cpp +++ b/hotspot/src/share/vm/runtime/atomic.cpp @@ -33,6 +33,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/atomic.inline.hpp b/hotspot/src/share/vm/runtime/atomic.inline.hpp index e89bf0c0887..2906719452d 100644 --- a/hotspot/src/share/vm/runtime/atomic.inline.hpp +++ b/hotspot/src/share/vm/runtime/atomic.inline.hpp @@ -57,6 +57,11 @@ # include "atomic_windows_x86.inline.hpp" #endif +// AIX +#ifdef TARGET_OS_ARCH_aix_ppc +# include "atomic_aix_ppc.inline.hpp" +#endif + // BSD #ifdef TARGET_OS_ARCH_bsd_x86 # include "atomic_bsd_x86.inline.hpp" diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 5db2fdc42cd..7af2b437219 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -61,6 +61,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "globals_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "globals_bsd.hpp" #endif @@ -88,6 +91,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "globals_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "globals_aix_ppc.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "globals_bsd_x86.hpp" #endif @@ -116,6 +122,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c1_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "c1_globals_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "c1_globals_bsd.hpp" #endif @@ -130,6 +139,9 @@ #ifdef TARGET_ARCH_arm # include "c2_globals_arm.hpp" #endif +#ifdef TARGET_ARCH_ppc +# include "c2_globals_ppc.hpp" +#endif #ifdef TARGET_OS_FAMILY_linux # include "c2_globals_linux.hpp" #endif @@ -139,6 +151,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c2_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "c2_globals_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "c2_globals_bsd.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 0c48e51818e..383f833590a 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -107,6 +107,9 @@ class InterfaceSupport: AllStatic { #ifdef TARGET_OS_FAMILY_windows # include "interfaceSupport_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "interfaceSupport_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "interfaceSupport_bsd.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp b/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp index 8374aa2a9d3..f6340923e32 100644 --- a/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp +++ b/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp @@ -50,6 +50,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "orderAccess_aix_ppc.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "orderAccess_bsd_x86.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index 7a2e240bd4f..c0100ce9728 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 03497e1973b..121259e5f3c 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -41,6 +41,10 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "jvm_aix.h" +# include +#endif #ifdef TARGET_OS_FAMILY_bsd # include "jvm_bsd.h" # include @@ -750,6 +754,10 @@ class os: AllStatic { #ifdef TARGET_OS_FAMILY_windows # include "os_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.hpp" +# include "os_posix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_posix.hpp" # include "os_bsd.hpp" @@ -778,6 +786,9 @@ class os: AllStatic { #ifdef TARGET_OS_ARCH_linux_ppc # include "os_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "os_aix_ppc.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "os_bsd_x86.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/osThread.hpp b/hotspot/src/share/vm/runtime/osThread.hpp index 1dfcb376163..02f3c0203fd 100644 --- a/hotspot/src/share/vm/runtime/osThread.hpp +++ b/hotspot/src/share/vm/runtime/osThread.hpp @@ -105,6 +105,9 @@ class OSThread: public CHeapObj { #ifdef TARGET_OS_FAMILY_windows # include "osThread_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "osThread_aix.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "osThread_bsd.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp index 6390ae1a045..d3a795b159a 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp @@ -56,10 +56,12 @@ # define __LO(x) *(1+(int*)&x) #endif +#if !defined(AIX) double copysign(double x, double y) { __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); return x; } +#endif /* * ==================================================== @@ -85,6 +87,7 @@ two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ hugeX = 1.0e+300, tiny = 1.0e-300; +#if !defined(AIX) double scalbn (double x, int n) { int k,hx,lx; hx = __HI(x); @@ -111,6 +114,7 @@ double scalbn (double x, int n) { __HI(x) = (hx&0x800fffff)|(k<<20); return x*twom54; } +#endif /* __ieee754_log(x) * Return the logrithm of x diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp index 74ed30cb003..a3590df8753 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp @@ -658,7 +658,7 @@ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ static double __kernel_cos(double x, double y) { - double a,hz,z,r,qx; + double a,h,z,r,qx; int ix; ix = __HI(x)&0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ @@ -675,9 +675,9 @@ static double __kernel_cos(double x, double y) __HI(qx) = ix-0x00200000; /* x/4 */ __LO(qx) = 0; } - hz = 0.5*z-qx; - a = one-qx; - return a - (hz - (z*r-x*y)); + h = 0.5*z-qx; + a = one-qx; + return a - (h - (z*r-x*y)); } } diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index a67b8a43a97..cdff326c47f 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1730,6 +1730,9 @@ public: #ifdef TARGET_OS_ARCH_linux_ppc # include "thread_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "thread_aix_ppc.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "thread_bsd_x86.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/thread.inline.hpp b/hotspot/src/share/vm/runtime/thread.inline.hpp index 30b02dbcb42..2a95d70b6f2 100644 --- a/hotspot/src/share/vm/runtime/thread.inline.hpp +++ b/hotspot/src/share/vm/runtime/thread.inline.hpp @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "thread_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "thread_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp index c2f7a9e4c2b..0f570f3d3ed 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp @@ -68,6 +68,9 @@ class ThreadLocalStorage : AllStatic { #ifdef TARGET_OS_ARCH_linux_ppc # include "threadLS_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "threadLS_aix_ppc.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "threadLS_bsd_x86.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/timer.cpp b/hotspot/src/share/vm/runtime/timer.cpp index 12c32660b04..ccb3322cedd 100644 --- a/hotspot/src/share/vm/runtime/timer.cpp +++ b/hotspot/src/share/vm/runtime/timer.cpp @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index 9096a034cef..30961c12c3f 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 8f7e78ef3ec..9a6dc052835 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -143,6 +143,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "vmStructs_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "vmStructs_aix_ppc.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "vmStructs_bsd_x86.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index e7d082d9f61..cdc05a3e0ce 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -177,6 +177,7 @@ const char* Abstract_VM_Version::jre_release_version() { #define OS LINUX_ONLY("linux") \ WINDOWS_ONLY("windows") \ SOLARIS_ONLY("solaris") \ + AIX_ONLY("aix") \ BSD_ONLY("bsd") #ifdef ZERO @@ -237,6 +238,9 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #endif #elif defined(__GNUC__) #define HOTSPOT_BUILD_COMPILER "gcc " __VERSION__ + #elif defined(__IBMCPP__) + #define HOTSPOT_BUILD_COMPILER "xlC " XSTR(__IBMCPP__) + #else #define HOTSPOT_BUILD_COMPILER "unknown compiler" #endif diff --git a/hotspot/src/share/vm/utilities/accessFlags.cpp b/hotspot/src/share/vm/utilities/accessFlags.cpp index 6ae8e74c21d..d9279428ed0 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.cpp +++ b/hotspot/src/share/vm/utilities/accessFlags.cpp @@ -34,6 +34,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index 01825d30225..23f8e551812 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/utilities/debug.hpp b/hotspot/src/share/vm/utilities/debug.hpp index 2450c8fe113..bb4f032c84b 100644 --- a/hotspot/src/share/vm/utilities/debug.hpp +++ b/hotspot/src/share/vm/utilities/debug.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_UTILITIES_DEBUG_HPP #define SHARE_VM_UTILITIES_DEBUG_HPP -#include "prims/jvm.h" #include "utilities/globalDefinitions.hpp" +#include "prims/jvm.h" #include diff --git a/hotspot/src/share/vm/utilities/decoder.cpp b/hotspot/src/share/vm/utilities/decoder.cpp index 5489fe6fefb..e4e466badac 100644 --- a/hotspot/src/share/vm/utilities/decoder.cpp +++ b/hotspot/src/share/vm/utilities/decoder.cpp @@ -33,6 +33,8 @@ #include "decoder_windows.hpp" #elif defined(__APPLE__) #include "decoder_machO.hpp" +#elif defined(AIX) + #include "decoder_aix.hpp" #else #include "decoder_elf.hpp" #endif @@ -67,6 +69,8 @@ AbstractDecoder* Decoder::create_decoder() { decoder = new (std::nothrow) WindowsDecoder(); #elif defined (__APPLE__) decoder = new (std::nothrow)MachODecoder(); +#elif defined(AIX) + decoder = new (std::nothrow)AIXDecoder(); #else decoder = new (std::nothrow)ElfDecoder(); #endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 181e80a0823..93f1f961cae 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -38,6 +38,9 @@ #ifdef TARGET_COMPILER_sparcWorks # include "utilities/globalDefinitions_sparcWorks.hpp" #endif +#ifdef TARGET_COMPILER_xlc +# include "utilities/globalDefinitions_xlc.hpp" +#endif #include "utilities/macros.hpp" diff --git a/hotspot/src/share/vm/utilities/histogram.hpp b/hotspot/src/share/vm/utilities/histogram.hpp index a969ed4578c..c03d488938a 100644 --- a/hotspot/src/share/vm/utilities/histogram.hpp +++ b/hotspot/src/share/vm/utilities/histogram.hpp @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 5d56097259b..0a061494cde 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -254,6 +254,14 @@ #define NOT_LINUX(code) code #endif +#ifdef AIX +#define AIX_ONLY(code) code +#define NOT_AIX(code) +#else +#define AIX_ONLY(code) +#define NOT_AIX(code) code +#endif + #ifdef SOLARIS #define SOLARIS_ONLY(code) code #define NOT_SOLARIS(code) diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 2f04fa0e437..8c5bc3363fa 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -39,6 +39,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif @@ -1040,7 +1043,7 @@ bufferedStream::~bufferedStream() { #ifndef PRODUCT -#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE) +#if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE) #include #include #include diff --git a/hotspot/src/share/vm/utilities/resourceHash.hpp b/hotspot/src/share/vm/utilities/resourceHash.hpp index 87cc8ffdb34..2fe5dec941a 100644 --- a/hotspot/src/share/vm/utilities/resourceHash.hpp +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp @@ -44,8 +44,12 @@ template bool primitive_equals(const K& k0, const K& k1) { template< typename K, typename V, - typename ResourceHashtableFns::hash_fn HASH = primitive_hash, - typename ResourceHashtableFns::equals_fn EQUALS = primitive_equals, + // xlC does not compile this: + // http://stackoverflow.com/questions/8532961/template-argument-of-type-that-is-defined-by-inner-typedef-from-other-template-c + //typename ResourceHashtableFns::hash_fn HASH = primitive_hash, + //typename ResourceHashtableFns::equals_fn EQUALS = primitive_equals, + unsigned (*HASH) (K const&) = primitive_hash, + bool (*EQUALS)(K const&, K const&) = primitive_equals, unsigned SIZE = 256 > class ResourceHashtable : public ResourceObj { diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index d3eafd5de47..84e61aeb984 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -53,6 +53,9 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_aix_ppc +# include "orderAccess_aix_ppc.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_bsd_x86 # include "orderAccess_bsd_x86.inline.hpp" #endif From c42cf5c3fd31e96c6bb6a7bd69fc14d6d4269d2d Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 6 Sep 2013 10:13:17 +0200 Subject: [PATCH 017/265] 8024379: Adapt PPC64 port to 8003424 Reviewed-by: coleenp --- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 40 +++++++++---------- hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp | 2 +- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 8567b1589b3..c72ebbb8b8a 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -2382,17 +2382,11 @@ void MacroAssembler::get_vm_result_2(Register metadata_result) { void MacroAssembler::encode_klass_not_null(Register dst, Register src) { if (src == noreg) src = dst; - if (Universe::narrow_klass_base() != NULL) { - // heapbased - assert(Universe::narrow_klass_shift() != 0, "sanity"); - sub(dst, src, R30); - srdi(dst, dst, Universe::narrow_klass_shift()); - } else if (Universe::narrow_klass_shift() != 0) { - // zerobased + assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); + load_const(R0, Universe::narrow_klass_base()); + sub(dst, src, R0); + if (Universe::narrow_klass_shift() != 0) { srdi(dst, src, Universe::narrow_klass_shift()); - } else if (src != dst) { - // unscaled - mr(dst, src); } } @@ -2407,18 +2401,14 @@ void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) void MacroAssembler::decode_klass_not_null(Register dst, Register src) { if (src == noreg) src = dst; - if (Universe::narrow_klass_base() != NULL) { - // heapbased - assert(Universe::narrow_klass_shift() != 0, "sanity"); - sldi(dst, src, Universe::narrow_klass_shift()); - add(dst, dst, R30); - } else if (Universe::narrow_klass_shift() != 0) { - // zerobased - sldi(dst, src, Universe::narrow_klass_shift()); - } else if (src != dst) { - // unscaled - mr(dst, src); + Register shifted_src = src; + assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); + if (Universe::narrow_klass_shift() != 0) { + shifted_src = dst; + sldi(shifted_src, src, Universe::narrow_klass_shift()); } + load_const(R0, Universe::narrow_klass_base()); + add(dst, shifted_src, R0); } void MacroAssembler::load_klass(Register dst, Register src) { @@ -2441,7 +2431,13 @@ void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) } void MacroAssembler::reinit_heapbase(Register d, Register tmp) { - if (UseCompressedOops || UseCompressedKlassPointers) { + if (Universe::heap() != NULL) { + if (Universe::narrow_oop_base() == NULL) { + Assembler::xorr(R30, R30, R30); + } else { + load_const(R30, Universe::narrow_ptrs_base(), tmp); + } + } else { load_const(R30, Universe::narrow_ptrs_base_addr(), tmp); ld(R30, 0, R30); } diff --git a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp index b7c17981705..4f365a46a05 100644 --- a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp @@ -58,7 +58,7 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { assert(type() == relocInfo::oop_type || type() == relocInfo::metadata_type, "how to encode else?"); narrowOop no = (type() == relocInfo::oop_type) ? - oopDesc::encode_heap_oop((oop)x) : oopDesc::encode_klass((Klass*)x); + oopDesc::encode_heap_oop((oop)x) : Klass::encode_klass((Klass*)x); nativeMovConstReg_at(addr())->set_narrow_oop(no, code()); } } else { From 56654216c44855537c54af36471f914cf2f1a435 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Fri, 6 Sep 2013 20:08:29 +0200 Subject: [PATCH 018/265] 8023034: PPC64 (part 14): Implement AIX/PPC64 support in HotSpot makefiles Reviewed-by: kvn --- hotspot/make/aix/Makefile | 377 ++++++++++++++++++ hotspot/make/aix/adlc_updater | 20 + hotspot/make/aix/makefiles/adjust-mflags.sh | 87 ++++ hotspot/make/aix/makefiles/adlc.make | 233 +++++++++++ hotspot/make/aix/makefiles/build_vm_def.sh | 18 + hotspot/make/aix/makefiles/buildtree.make | 364 +++++++++++++++++ hotspot/make/aix/makefiles/compiler2.make | 32 ++ hotspot/make/aix/makefiles/core.make | 33 ++ hotspot/make/aix/makefiles/debug.make | 41 ++ hotspot/make/aix/makefiles/defs.make | 231 +++++++++++ hotspot/make/aix/makefiles/dtrace.make | 27 ++ hotspot/make/aix/makefiles/fastdebug.make | 73 ++++ hotspot/make/aix/makefiles/jsig.make | 87 ++++ hotspot/make/aix/makefiles/jvmti.make | 118 ++++++ hotspot/make/aix/makefiles/mapfile-vers-debug | 274 +++++++++++++ hotspot/make/aix/makefiles/mapfile-vers-jsig | 38 ++ .../make/aix/makefiles/mapfile-vers-product | 267 +++++++++++++ hotspot/make/aix/makefiles/ppc64.make | 94 +++++ hotspot/make/aix/makefiles/product.make | 58 +++ hotspot/make/aix/makefiles/rules.make | 203 ++++++++++ hotspot/make/aix/makefiles/sa.make | 116 ++++++ hotspot/make/aix/makefiles/saproc.make | 117 ++++++ hotspot/make/aix/makefiles/top.make | 144 +++++++ hotspot/make/aix/makefiles/trace.make | 120 ++++++ hotspot/make/aix/makefiles/vm.make | 377 ++++++++++++++++++ hotspot/make/aix/makefiles/xlc.make | 159 ++++++++ hotspot/make/aix/platform_ppc64 | 17 + hotspot/make/defs.make | 8 +- 28 files changed, 3731 insertions(+), 2 deletions(-) create mode 100644 hotspot/make/aix/Makefile create mode 100644 hotspot/make/aix/adlc_updater create mode 100644 hotspot/make/aix/makefiles/adjust-mflags.sh create mode 100644 hotspot/make/aix/makefiles/adlc.make create mode 100644 hotspot/make/aix/makefiles/build_vm_def.sh create mode 100644 hotspot/make/aix/makefiles/buildtree.make create mode 100644 hotspot/make/aix/makefiles/compiler2.make create mode 100644 hotspot/make/aix/makefiles/core.make create mode 100644 hotspot/make/aix/makefiles/debug.make create mode 100644 hotspot/make/aix/makefiles/defs.make create mode 100644 hotspot/make/aix/makefiles/dtrace.make create mode 100644 hotspot/make/aix/makefiles/fastdebug.make create mode 100644 hotspot/make/aix/makefiles/jsig.make create mode 100644 hotspot/make/aix/makefiles/jvmti.make create mode 100644 hotspot/make/aix/makefiles/mapfile-vers-debug create mode 100644 hotspot/make/aix/makefiles/mapfile-vers-jsig create mode 100644 hotspot/make/aix/makefiles/mapfile-vers-product create mode 100644 hotspot/make/aix/makefiles/ppc64.make create mode 100644 hotspot/make/aix/makefiles/product.make create mode 100644 hotspot/make/aix/makefiles/rules.make create mode 100644 hotspot/make/aix/makefiles/sa.make create mode 100644 hotspot/make/aix/makefiles/saproc.make create mode 100644 hotspot/make/aix/makefiles/top.make create mode 100644 hotspot/make/aix/makefiles/trace.make create mode 100644 hotspot/make/aix/makefiles/vm.make create mode 100644 hotspot/make/aix/makefiles/xlc.make create mode 100644 hotspot/make/aix/platform_ppc64 diff --git a/hotspot/make/aix/Makefile b/hotspot/make/aix/Makefile new file mode 100644 index 00000000000..19bab5494bc --- /dev/null +++ b/hotspot/make/aix/Makefile @@ -0,0 +1,377 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 makefile creates a build tree and lights off a build. +# You can go back into the build tree and perform rebuilds or +# incremental builds as desired. Be sure to reestablish +# environment variable settings for LD_LIBRARY_PATH and JAVA_HOME. + +# The make process now relies on java and javac. These can be +# specified either implicitly on the PATH, by setting the +# (JDK-inherited) ALT_BOOTDIR environment variable to full path to a +# JDK in which bin/java and bin/javac are present and working (e.g., +# /usr/local/java/jdk1.3/solaris), or via the (JDK-inherited) +# default BOOTDIR path value. Note that one of ALT_BOOTDIR +# or BOOTDIR has to be set. We do *not* search javac, javah, rmic etc. +# from the PATH. +# +# One can set ALT_BOOTDIR or BOOTDIR to point to a jdk that runs on +# an architecture that differs from the target architecture, as long +# as the bootstrap jdk runs under the same flavor of OS as the target +# (i.e., if the target is linux, point to a jdk that runs on a linux +# box). In order to use such a bootstrap jdk, set the make variable +# REMOTE to the desired remote command mechanism, e.g., +# +# make REMOTE="rsh -l me myotherlinuxbox" + +# Along with VM, Serviceability Agent (SA) is built for SA/JDI binding. +# JDI binding on SA produces two binaries: +# 1. sa-jdi.jar - This is built before building libjvm.so +# Please refer to ./makefiles/sa.make +# 2. libsa.so - Native library for SA - This is built after +# libjsig.so (signal interposition library) +# Please refer to ./makefiles/vm.make +# If $(GAMMADIR)/agent dir is not present, SA components are not built. + +# No tests on Aix. +TEST_IN_BUILD=false + +ifeq ($(GAMMADIR),) +include ../../make/defs.make +else +include $(GAMMADIR)/make/defs.make +endif +include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make + +ifndef CC_INTERP + ifndef FORCE_TIERED + FORCE_TIERED=1 + endif +endif + +ifdef LP64 + ifeq ("$(filter $(LP64_ARCH),$(BUILDARCH))","") + _JUNK_ := $(shell echo >&2 \ + $(OSNAME) $(ARCH) "*** ERROR: this platform does not support 64-bit compilers!") + @exit 1 + endif +endif + +# we need to set up LP64 correctly to satisfy sanity checks in adlc +ifneq ("$(filter $(LP64_ARCH),$(BUILDARCH))","") + MFLAGS += " LP64=1 " +endif + +# pass USE_SUNCC further, through MFLAGS +ifdef USE_SUNCC + MFLAGS += " USE_SUNCC=1 " +endif + +# The following renders pathnames in generated Makefiles valid on +# machines other than the machine containing the build tree. +# +# For example, let's say my build tree lives on /files12 on +# exact.east.sun.com. This logic will cause GAMMADIR to begin with +# /net/exact/files12/... +# +# We only do this on SunOS variants, for a couple of reasons: +# * It is extremely rare that source trees exist on other systems +# * It has been claimed that the Linux automounter is flakey, so +# changing GAMMADIR in a way that exercises the automounter could +# prove to be a source of unreliability in the build process. +# Obviously, this Makefile is only relevant on SunOS boxes to begin +# with, but the SunOS conditionalization will make it easier to +# combine Makefiles in the future (assuming we ever do that). + +ifeq ($(OSNAME),solaris) + + # prepend current directory to relative pathnames. + NEW_GAMMADIR := \ + $(shell echo $(GAMMADIR) | \ + sed -e "s=^\([^/].*\)=$(shell pwd)/\1=" \ + ) + unexport NEW_GAMMADIR + + # If NEW_GAMMADIR doesn't already start with "/net/": + ifeq ($(strip $(filter /net/%,$(NEW_GAMMADIR))),) + # prepend /net/$(HOST) + # remove /net/$(HOST) if name already began with /home/ + # remove /net/$(HOST) if name already began with /java/ + # remove /net/$(HOST) if name already began with /lab/ + NEW_GAMMADIR := \ + $(shell echo $(NEW_GAMMADIR) | \ + sed -e "s=^\(.*\)=/net/$(HOST)\1=" \ + -e "s=^/net/$(HOST)/home/=/home/=" \ + -e "s=^/net/$(HOST)/java/=/java/=" \ + -e "s=^/net/$(HOST)/lab/=/lab/=" \ + ) + # Don't use the new value for GAMMADIR unless a file with the new + # name actually exists. + ifneq ($(wildcard $(NEW_GAMMADIR)),) + GAMMADIR := $(NEW_GAMMADIR) + endif + endif + +endif + +# BUILDARCH is set to "zero" for Zero builds. VARIANTARCH +# is used to give the build directories meaningful names. +VARIANTARCH = $(subst i386,i486,$(ZERO_LIBARCH)) + +# There is a (semi-) regular correspondence between make targets and actions: +# +# Target Tree Type Build Dir +# +# debug compiler2 __compiler2/debug +# fastdebug compiler2 __compiler2/fastdebug +# optimized compiler2 __compiler2/optimized +# product compiler2 __compiler2/product +# +# debug1 compiler1 __compiler1/debug +# fastdebug1 compiler1 __compiler1/fastdebug +# optimized1 compiler1 __compiler1/optimized +# product1 compiler1 __compiler1/product +# +# debugcore core __core/debug +# fastdebugcore core __core/fastdebug +# optimizedcore core __core/optimized +# productcore core __core/product +# +# debugzero zero __zero/debug +# fastdebugzero zero __zero/fastdebug +# optimizedzero zero __zero/optimized +# productzero zero __zero/product +# +# debugshark shark __shark/debug +# fastdebugshark shark __shark/fastdebug +# optimizedshark shark __shark/optimized +# productshark shark __shark/product +# +# fastdebugminimal1 minimal1 __minimal1/fastdebug +# productminimal1 minimal1 __minimal1/product +# +# What you get with each target: +# +# debug* - debug compile with asserts enabled +# fastdebug* - optimized compile, but with asserts enabled +# optimized* - optimized compile, no asserts +# product* - the shippable thing: optimized compile, no asserts, -DPRODUCT + +# This target list needs to be coordinated with the usage message +# in the build.sh script: +TARGETS = debug fastdebug optimized product + +ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) + SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs +else + SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs +endif +SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) +SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) +SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) +SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) +SUBDIRS_ZERO = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS)) +SUBDIRS_SHARK = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS)) +SUBDIRS_MINIMAL1 = $(addprefix $(OSNAME)_$(BUILDARCH)_minimal1/,$(TARGETS)) + +TARGETS_C2 = $(TARGETS) +TARGETS_C1 = $(addsuffix 1,$(TARGETS)) +TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) +TARGETS_CORE = $(addsuffix core,$(TARGETS)) +TARGETS_ZERO = $(addsuffix zero,$(TARGETS)) +TARGETS_SHARK = $(addsuffix shark,$(TARGETS)) +TARGETS_MINIMAL1 = $(addsuffix minimal1,$(TARGETS)) + +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make +BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) +BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) ZIPEXE=$(ZIPEXE) + +BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS) + +#------------------------------------------------------------------------------- + +# Could make everything by default, but that would take a while. +all: + @echo "Try '$(MAKE) ...' where is one or more of" + @echo " $(TARGETS_C2)" + @echo " $(TARGETS_C1)" + @echo " $(TARGETS_CORE)" + @echo " $(TARGETS_ZERO)" + @echo " $(TARGETS_SHARK)" + @echo " $(TARGETS_MINIMAL1)" + +checks: check_os_version check_j2se_version + +# We do not want people accidentally building on old systems (e.g. Linux 2.2.x, +# Solaris 2.5.1, 2.6). +# Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok. + +SUPPORTED_OS_VERSION = AIX +OS_VERSION := $(shell uname -a) +EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION)) + +check_os_version: +ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),) + $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1; +endif + +# jvmti.make requires XSLT (J2SE 1.4.x or newer): +XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory +# If not found then fail fast. +check_j2se_version: + $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \ + if [ $$? -ne 0 ]; then \ + $(REMOTE) $(RUN.JAVA) -version; \ + echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \ + "to bootstrap this build" 1>&2; \ + exit 1; \ + fi + +$(SUBDIRS_TIERED): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=tiered + +$(SUBDIRS_C2): $(BUILDTREE_MAKE) +ifeq ($(FORCE_TIERED),1) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1 +else + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=compiler2 +endif + +$(SUBDIRS_C1): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=compiler1 + +$(SUBDIRS_CORE): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=core + +$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH) + +$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH) + +$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=minimal1 + + +platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in + $(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@ + +# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME + +$(TARGETS_C2): $(SUBDIRS_C2) + cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_TIERED): $(SUBDIRS_TIERED) + cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_C1): $(SUBDIRS_C1) + cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_CORE): $(SUBDIRS_CORE) + cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_ZERO): $(SUBDIRS_ZERO) + cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_SHARK): $(SUBDIRS_SHARK) + cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_MINIMAL1): $(SUBDIRS_MINIMAL1) + cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_minimal1/$(patsubst %minimal1,%,$@) && $(MAKE) $(MFLAGS) install +endif + +# Just build the tree, and nothing else: +tree: $(SUBDIRS_C2) +tree1: $(SUBDIRS_C1) +treecore: $(SUBDIRS_CORE) +treezero: $(SUBDIRS_ZERO) +treeshark: $(SUBDIRS_SHARK) +treeminimal1: $(SUBDIRS_MINIMAL1) + +# Doc target. This is the same for all build options. +# Hence create a docs directory beside ...$(ARCH)_[...] +# We specify 'BUILD_FLAVOR=product' so that the proper +# ENABLE_FULL_DEBUG_SYMBOLS value is used. +docs: checks + $(QUIETLY) mkdir -p $(SUBDIR_DOCS) + $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) BUILD_FLAVOR=product jvmtidocs + +# Synonyms for win32-like targets. +compiler2: debug product + +compiler1: debug1 product1 + +core: debugcore productcore + +zero: debugzero productzero + +shark: debugshark productshark + +clean_docs: + rm -rf $(SUBDIR_DOCS) + +clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark clean_minimal1: + rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) + +clean: clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_minimal1 clean_docs + +include $(GAMMADIR)/make/cscope.make + +#------------------------------------------------------------------------------- + +.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) $(TARGETS_MINIMAL1) +.PHONY: tree tree1 treecore treezero treeshark +.PHONY: all compiler1 compiler2 core zero shark +.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs +.PHONY: checks check_os_version check_j2se_version diff --git a/hotspot/make/aix/adlc_updater b/hotspot/make/aix/adlc_updater new file mode 100644 index 00000000000..6d31b792c05 --- /dev/null +++ b/hotspot/make/aix/adlc_updater @@ -0,0 +1,20 @@ +#! /bin/sh +# +# This file is used by adlc.make to selectively update generated +# adlc files. Because source and target diretories are relative +# paths, this file is copied to the target build directory before +# use. +# +# adlc-updater +# +fix_lines() { + # repair bare #line directives in $1 to refer to $2 + awk < $1 > $1+ ' + /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} + {print} + ' F2=$2 + mv $1+ $1 +} +fix_lines $2/$1 $3/$1 +[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ +( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 ) diff --git a/hotspot/make/aix/makefiles/adjust-mflags.sh b/hotspot/make/aix/makefiles/adjust-mflags.sh new file mode 100644 index 00000000000..df1aa625b77 --- /dev/null +++ b/hotspot/make/aix/makefiles/adjust-mflags.sh @@ -0,0 +1,87 @@ +#! /bin/sh +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 script is used only from top.make. +# The macro $(MFLAGS-adjusted) calls this script to +# adjust the "-j" arguments to take into account +# the HOTSPOT_BUILD_JOBS variable. The default +# handling of the "-j" argument by gnumake does +# not meet our needs, so we must adjust it ourselves. + +# This argument adjustment applies to two recursive +# calls to "$(MAKE) $(MFLAGS-adjusted)" in top.make. +# One invokes adlc.make, and the other invokes vm.make. +# The adjustment propagates the desired concurrency +# level down to the sub-make (of the adlc or vm). +# The default behavior of gnumake is to run all +# sub-makes without concurrency ("-j1"). + +# Also, we use a make variable rather than an explicit +# "-j" argument to control this setting, so that +# the concurrency setting (which must be tuned separately +# for each MP system) can be set via an environment variable. +# The recommended setting is 1.5x to 2x the number of available +# CPUs on the MP system, which is large enough to keep the CPUs +# busy (even though some jobs may be I/O bound) but not too large, +# we may presume, to overflow the system's swap space. + +set -eu + +default_build_jobs=4 + +case $# in +[12]) true;; +*) >&2 echo "Usage: $0 ${MFLAGS} ${HOTSPOT_BUILD_JOBS}"; exit 2;; +esac + +MFLAGS=$1 +HOTSPOT_BUILD_JOBS=${2-} + +# Normalize any -jN argument to the form " -j${HBJ}" +MFLAGS=` + echo "$MFLAGS" \ + | sed ' + s/^-/ -/ + s/ -\([^ ][^ ]*\)j/ -\1 -j/ + s/ -j[0-9][0-9]*/ -j/ + s/ -j\([^ ]\)/ -j -\1/ + s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/ + ' ` + +case ${HOTSPOT_BUILD_JOBS} in \ + +'') case ${MFLAGS} in + *\ -j*) + >&2 echo "# Note: -jN is ineffective for setting parallelism in this makefile." + >&2 echo "# please set HOTSPOT_BUILD_JOBS=${default_build_jobs} in the command line or environment." + esac;; + +?*) case ${MFLAGS} in + *\ -j*) true;; + *) MFLAGS="-j${HOTSPOT_BUILD_JOBS} ${MFLAGS}";; + esac;; +esac + +echo "${MFLAGS}" diff --git a/hotspot/make/aix/makefiles/adlc.make b/hotspot/make/aix/makefiles/adlc.make new file mode 100644 index 00000000000..d104860b432 --- /dev/null +++ b/hotspot/make/aix/makefiles/adlc.make @@ -0,0 +1,233 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 makefile (adlc.make) is included from the adlc.make in the +# build directories. +# It knows how to compile, link, and run the adlc. + +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/rules.make + +# ######################################################################### + +# OUTDIR must be the same as AD_Dir = $(GENERATED)/adfiles in top.make: +GENERATED = ../generated +OUTDIR = $(GENERATED)/adfiles + +ARCH = $(Platform_arch) +OS = $(Platform_os_family) + +SOURCE.AD = $(OUTDIR)/$(OS)_$(Platform_arch_model).ad + +ifeq ("${Platform_arch_model}", "${Platform_arch}") + SOURCES.AD = \ + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \ + $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad) +else + SOURCES.AD = \ + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \ + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch).ad) \ + $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad) +endif + +EXEC = $(OUTDIR)/adlc + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(GAMMADIR)/src/share/vm/adlc +VPATH += $(Src_Dirs_V:%=%:) + +# set INCLUDES for C preprocessor +Src_Dirs_I += $(GAMMADIR)/src/share/vm/adlc $(GENERATED) +INCLUDES += $(Src_Dirs_I:%=-I%) + +# set flags for adlc compilation +CXXFLAGS = $(SYSDEFS) $(INCLUDES) + +# Force assertions on. +CXXFLAGS += -DASSERT + +# CFLAGS_WARN holds compiler options to suppress/enable warnings. +# Suppress warnings (for now) +CFLAGS_WARN = -w +CFLAGS += $(CFLAGS_WARN) + +OBJECTNAMES = \ + adlparse.o \ + archDesc.o \ + arena.o \ + dfa.o \ + dict2.o \ + filebuff.o \ + forms.o \ + formsopt.o \ + formssel.o \ + main.o \ + adlc-opcodes.o \ + output_c.o \ + output_h.o \ + +OBJECTS = $(OBJECTNAMES:%=$(OUTDIR)/%) + +GENERATEDNAMES = \ + ad_$(Platform_arch_model).cpp \ + ad_$(Platform_arch_model).hpp \ + ad_$(Platform_arch_model)_clone.cpp \ + ad_$(Platform_arch_model)_expand.cpp \ + ad_$(Platform_arch_model)_format.cpp \ + ad_$(Platform_arch_model)_gen.cpp \ + ad_$(Platform_arch_model)_misc.cpp \ + ad_$(Platform_arch_model)_peephole.cpp \ + ad_$(Platform_arch_model)_pipeline.cpp \ + adGlobals_$(Platform_arch_model).hpp \ + dfa_$(Platform_arch_model).cpp \ + +GENERATEDFILES = $(GENERATEDNAMES:%=$(OUTDIR)/%) + +# ######################################################################### + +all: $(EXEC) + +$(EXEC) : $(OBJECTS) + @echo Making adlc + $(QUIETLY) $(HOST.LINK_NOPROF.CXX) -o $(EXEC) $(OBJECTS) + +# Random dependencies: +$(OBJECTS): opcodes.hpp classes.hpp adlc.hpp adlcVMDeps.hpp adlparse.hpp archDesc.hpp arena.hpp dict2.hpp filebuff.hpp forms.hpp formsopt.hpp formssel.hpp + +# The source files refer to ostream.h, which sparcworks calls iostream.h +$(OBJECTS): ostream.h + +ostream.h : + @echo >$@ '#include ' + +dump: + : OUTDIR=$(OUTDIR) + : OBJECTS=$(OBJECTS) + : products = $(GENERATEDFILES) + +all: $(GENERATEDFILES) + +$(GENERATEDFILES): refresh_adfiles + +# Get a unique temporary directory name, so multiple makes can run in parallel. +# Note that product files are updated via "mv", which is atomic. +TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$) + +# Debuggable by default +CFLAGS += -g + +# Pass -D flags into ADLC. +ADLCFLAGS += $(SYSDEFS) + +# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO. +ADLCFLAGS += -q -T + +# Normally, debugging is done directly on the ad_*.cpp files. +# But -g will put #line directives in those files pointing back to .ad. +# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives +# so skip it for 3.2 and ealier. +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +ADLCFLAGS += -g +endif + +ifdef LP64 +ADLCFLAGS += -D_LP64 +else +ADLCFLAGS += -U_LP64 +endif + +# +# adlc_updater is a simple sh script, under sccs control. It is +# used to selectively update generated adlc files. This should +# provide a nice compilation speed improvement. +# +ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS) +ADLC_UPDATER = adlc_updater +$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) + $(QUIETLY) cp $< $@; chmod +x $@ + +# This action refreshes all generated adlc files simultaneously. +# The way it works is this: +# 1) create a scratch directory to work in. +# 2) if the current working directory does not have $(ADLC_UPDATER), copy it. +# 3) run the compiled adlc executable. This will create new adlc files in the scratch directory. +# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files. +# 5) If we actually updated any files, echo a notice. +# +refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER) + @rm -rf $(TEMPDIR); mkdir $(TEMPDIR) + $(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \ + -c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \ + || { rm -rf $(TEMPDIR); exit 1; } + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_clone.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_expand.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_format.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_gen.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_misc.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_peephole.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_pipeline.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) adGlobals_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) dfa_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) [ -f $(TEMPDIR)/made-change ] \ + || echo "Rescanned $(SOURCE.AD) but encountered no changes." + $(QUIETLY) rm -rf $(TEMPDIR) + + +# ######################################################################### + +$(SOURCE.AD): $(SOURCES.AD) + $(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD) + +#PROCESS_AD_FILES = cat +# Pass through #line directives, in case user enables -g option above: +PROCESS_AD_FILES = awk '{ \ + if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \ + if (need_lineno && $$0 !~ /\/\//) \ + { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \ + print }' + +$(OUTDIR)/%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(HOST.COMPILE.CXX) -o $@ $< $(COMPILE_DONE) + +# Some object files are given a prefix, to disambiguate +# them from objects of the same name built for the VM. +$(OUTDIR)/adlc-%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(HOST.COMPILE.CXX) -o $@ $< $(COMPILE_DONE) + +# ######################################################################### + +clean: + rm $(OBJECTS) + +cleanall: + rm $(OBJECTS) $(EXEC) + +# ######################################################################### + +.PHONY: all dump refresh_adfiles clean cleanall diff --git a/hotspot/make/aix/makefiles/build_vm_def.sh b/hotspot/make/aix/makefiles/build_vm_def.sh new file mode 100644 index 00000000000..8d8e8fd2955 --- /dev/null +++ b/hotspot/make/aix/makefiles/build_vm_def.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# If we're cross compiling use that path for nm +if [ "$CROSS_COMPILE_ARCH" != "" ]; then +NM=$ALT_COMPILER_PATH/nm +else +# On AIX we have to prevent that we pick up the 'nm' version from the GNU binutils +# which may be installed under /opt/freeware/bin. So better use an absolute path here! +NM=/usr/bin/nm +fi + +$NM -X64 -B -C $* \ + | awk '{ + if (($2="d" || $2="D") && ($3 ~ /^__vft/ || $3 ~ /^gHotSpotVM/)) print "\t" $3 ";" + if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" + if ($3 ~ /^SharedArchivePath__9Arguments$/) print "\t" $3 ";" + }' \ + | sort -u diff --git a/hotspot/make/aix/makefiles/buildtree.make b/hotspot/make/aix/makefiles/buildtree.make new file mode 100644 index 00000000000..882533024ea --- /dev/null +++ b/hotspot/make/aix/makefiles/buildtree.make @@ -0,0 +1,364 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Usage: +# +# $(MAKE) -f buildtree.make SRCARCH=srcarch BUILDARCH=buildarch LIBARCH=libarch +# GAMMADIR=dir OS_FAMILY=os VARIANT=variant +# +# The macros ARCH, GAMMADIR, OS_FAMILY and VARIANT must be defined in the +# environment or on the command-line: +# +# ARCH - sparc, i486, ... HotSpot cpu and os_cpu source directory +# BUILDARCH - build directory +# LIBARCH - the corresponding directory in JDK/JRE +# GAMMADIR - top of workspace +# OS_FAMILY - operating system +# VARIANT - core, compiler1, compiler2, or tiered +# HOTSPOT_RELEASE_VERSION - .-b (11.0-b07) +# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty +# JRE_RELEASE_VERSION - .. (1.7.0) +# +# Builds the directory trees with makefiles plus some convenience files in +# each directory: +# +# Makefile - for "make foo" +# flags.make - with macro settings +# vm.make - to support making "$(MAKE) -v vm.make" in makefiles +# adlc.make - +# trace.make - generate tracing event and type definitions +# jvmti.make - generate JVMTI bindings from the spec (JSR-163) +# sa.make - generate SA jar file and natives +# +# The makefiles are split this way so that "make foo" will run faster by not +# having to read the dependency files for the vm. + +-include $(SPEC) +include $(GAMMADIR)/make/scm.make +include $(GAMMADIR)/make/defs.make +include $(GAMMADIR)/make/altsrc.make + + +# 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details. +QUIETLY$(MAKE_VERBOSE) = @ + +ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) + PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero +else + ifdef USE_SUNCC + PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc + else + PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) + endif +endif + +# Allow overriding of the arch part of the directory but default +# to BUILDARCH if nothing is specified +ifeq ($(VARIANTARCH),) + VARIANTARCH=$(BUILDARCH) +endif + +ifdef FORCE_TIERED +ifeq ($(VARIANT),tiered) +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_compiler2 +else +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT) +endif +else +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT) +endif + +# +# We do two levels of exclusion in the shared directory. +# TOPLEVEL excludes are pruned, they are not recursively searched, +# but lower level directories can be named without fear of collision. +# ALWAYS excludes are excluded at any level in the directory tree. +# + +ALWAYS_EXCLUDE_DIRS = $(SCM_DIRS) + +ifeq ($(VARIANT),tiered) +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name agent +else +ifeq ($(VARIANT),compiler2) +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name c1 -o -name agent +else +# compiler1 and core use the same exclude list +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name opto -o -name libadt -o -name agent +endif +endif + +# Get things from the platform file. +COMPILER = $(shell sed -n 's/^compiler[ ]*=[ ]*//p' $(PLATFORM_FILE)) + +SIMPLE_DIRS = \ + $(PLATFORM_DIR)/generated/dependencies \ + $(PLATFORM_DIR)/generated/adfiles \ + $(PLATFORM_DIR)/generated/jvmtifiles \ + $(PLATFORM_DIR)/generated/tracefiles + +TARGETS = debug fastdebug optimized product +SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) + +# For dependencies and recursive makes. +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make + +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make + +BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ + SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) + +# Define variables to be set in flags.make. +# Default values are set in make/defs.make. +ifeq ($(HOTSPOT_BUILD_VERSION),) + HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION) +else + HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION) +endif +# Set BUILD_USER from system-dependent hints: $LOGNAME, $(whoami) +ifndef HOTSPOT_BUILD_USER + HOTSPOT_BUILD_USER := $(shell echo $$LOGNAME) +endif +ifndef HOTSPOT_BUILD_USER + HOTSPOT_BUILD_USER := $(shell whoami) +endif +# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro +# or make/hotspot_distro. +ifndef HOTSPOT_VM_DISTRO + ifeq ($(call if-has-altsrc,$(HS_COMMON_SRC)/,true,false),true) + include $(GAMMADIR)/make/hotspot_distro + else + include $(GAMMADIR)/make/openjdk_distro + endif +endif + +# if hotspot-only build and/or OPENJDK isn't passed down, need to set OPENJDK +ifndef OPENJDK + ifneq ($(call if-has-altsrc,$(HS_COMMON_SRC)/,true,false),true) + OPENJDK=true + endif +endif + +BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) + +BUILDTREE = \ + $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_TARGETS) $(BUILDTREE_VARS) + +BUILDTREE_COMMENT = echo "\# Generated by $(BUILDTREE_MAKE)" + +all: $(SUBMAKE_DIRS) + +# Run make in each subdirectory recursively. +$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE + $(QUIETLY) [ -d $@ ] || { mkdir -p $@; } + $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F) + $(QUIETLY) touch $@ + +$(SIMPLE_DIRS): + $(QUIETLY) mkdir -p $@ + +# Convenience macro which takes a source relative path, applies $(1) to the +# absolute path, and then replaces $(GAMMADIR) in the result with a +# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. +gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2))) + +# This bit is needed to enable local rebuilds. +# Unless the makefile itself sets LP64, any environmental +# setting of LP64 will interfere with the build. +LP64_SETTING/32 = LP64 = \#empty +LP64_SETTING/64 = LP64 = 1 + +DATA_MODE/ppc64 = 64 + +DATA_MODE = $(DATA_MODE/$(BUILDARCH)) + +flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ + sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \ + echo; \ + echo "GAMMADIR = $(GAMMADIR)"; \ + echo "HS_ALT_MAKE = $(HS_ALT_MAKE)"; \ + echo "OSNAME = $(OSNAME)"; \ + echo "SYSDEFS = \$$(Platform_sysdefs)"; \ + echo "SRCARCH = $(SRCARCH)"; \ + echo "BUILDARCH = $(BUILDARCH)"; \ + echo "LIBARCH = $(LIBARCH)"; \ + echo "TARGET = $(TARGET)"; \ + echo "HS_BUILD_VER = $(HS_BUILD_VER)"; \ + echo "JRE_RELEASE_VER = $(JRE_RELEASE_VERSION)"; \ + echo "SA_BUILD_VERSION = $(HS_BUILD_VER)"; \ + echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \ + echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \ + echo "OPENJDK = $(OPENJDK)"; \ + echo "$(LP64_SETTING/$(DATA_MODE))"; \ + echo; \ + echo "# Used for platform dispatching"; \ + echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \ + echo "TARGET_DEFINES += -DTARGET_ARCH_\$$(Platform_arch)"; \ + echo "TARGET_DEFINES += -DTARGET_ARCH_MODEL_\$$(Platform_arch_model)"; \ + echo "TARGET_DEFINES += -DTARGET_OS_ARCH_\$$(Platform_os_arch)"; \ + echo "TARGET_DEFINES += -DTARGET_OS_ARCH_MODEL_\$$(Platform_os_arch_model)"; \ + echo "TARGET_DEFINES += -DTARGET_COMPILER_\$$(Platform_compiler)"; \ + echo "CFLAGS += \$$(TARGET_DEFINES)"; \ + echo; \ + echo "Src_Dirs_V = \\"; \ + sed 's/$$/ \\/;s|$(GAMMADIR)|$$(GAMMADIR)|' ../shared_dirs.lst; \ + echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo; \ + echo "Src_Dirs_I = \\"; \ + echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \ + echo "$(call gamma-path,commonsrc,share/vm/prims) \\"; \ + echo "$(call gamma-path,altsrc,share/vm) \\"; \ + echo "$(call gamma-path,commonsrc,share/vm) \\"; \ + echo "$(call gamma-path,altsrc,share/vm/precompiled) \\"; \ + echo "$(call gamma-path,commonsrc,share/vm/precompiled) \\"; \ + echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + [ -n "$(CFLAGS_BROWSE)" ] && \ + echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \ + echo && echo "ENABLE_FULL_DEBUG_SYMBOLS = $(ENABLE_FULL_DEBUG_SYMBOLS)"; \ + [ -n "$(OBJCOPY)" ] && \ + echo && echo "OBJCOPY = $(OBJCOPY)"; \ + [ -n "$(STRIP_POLICY)" ] && \ + echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \ + [ -n "$(ZIP_DEBUGINFO_FILES)" ] && \ + echo && echo "ZIP_DEBUGINFO_FILES = $(ZIP_DEBUGINFO_FILES)"; \ + [ -n "$(ZIPEXE)" ] && \ + echo && echo "ZIPEXE = $(ZIPEXE)"; \ + [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ + echo && \ + echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ + echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \ + [ -n "$(INCLUDE_TRACE)" ] && \ + echo && echo "INCLUDE_TRACE = $(INCLUDE_TRACE)"; \ + echo; \ + [ -n "$(SPEC)" ] && \ + echo "include $(SPEC)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ + echo "include \$$(GAMMADIR)/make/excludeSrc.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ + ) > $@ + +flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ + ) > $@ + +../shared_dirs.lst: $(BUILDTREE_MAKE) $(GAMMADIR)/src/share/vm + @echo Creating directory list $@ + $(QUIETLY) if [ -d $(HS_ALT_SRC)/share/vm ]; then \ + find $(HS_ALT_SRC)/share/vm/* -prune \ + -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \ + \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; > $@; \ + fi; + $(QUIETLY) find $(HS_COMMON_SRC)/share/vm/* -prune \ + -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \ + \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; >> $@ + +Makefile: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/top.make"; \ + ) > $@ + +vm.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo include flags_vm.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +adlc.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +jvmti.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +trace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +sa.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +FORCE: + +.PHONY: all FORCE diff --git a/hotspot/make/aix/makefiles/compiler2.make b/hotspot/make/aix/makefiles/compiler2.make new file mode 100644 index 00000000000..73f544f118d --- /dev/null +++ b/hotspot/make/aix/makefiles/compiler2.make @@ -0,0 +1,32 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Sets make macros for making server version of VM + +TYPE=COMPILER2 + +VM_SUBDIR = server + +CFLAGS += -DCOMPILER2 diff --git a/hotspot/make/aix/makefiles/core.make b/hotspot/make/aix/makefiles/core.make new file mode 100644 index 00000000000..56d85c8fc16 --- /dev/null +++ b/hotspot/make/aix/makefiles/core.make @@ -0,0 +1,33 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Sets make macros for making core version of VM + +# Select which files to use (in top.make) +TYPE=CORE + +# There is no "core" directory in JDK. Install core build in server directory. +VM_SUBDIR = server + +# Note: macros.hpp defines CORE diff --git a/hotspot/make/aix/makefiles/debug.make b/hotspot/make/aix/makefiles/debug.make new file mode 100644 index 00000000000..5e2cacd365d --- /dev/null +++ b/hotspot/make/aix/makefiles/debug.make @@ -0,0 +1,41 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Sets make macros for making debug version of VM + +# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make +DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) +DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) +CFLAGS += $(DEBUG_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/aix/makefiles/mapfile-vers-debug + +VERSION = debug +SYSDEFS += -DASSERT -DDEBUG +PICFLAGS = DEFAULT diff --git a/hotspot/make/aix/makefiles/defs.make b/hotspot/make/aix/makefiles/defs.make new file mode 100644 index 00000000000..64746ab67d5 --- /dev/null +++ b/hotspot/make/aix/makefiles/defs.make @@ -0,0 +1,231 @@ +# +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# The common definitions for hotspot AIX builds. +# Include the top level defs.make under make directory instead of this one. +# This file is included into make/defs.make. + +SLASH_JAVA ?= /java + +# Need PLATFORM (os-arch combo names) for jdk and hotspot, plus libarch name +#ARCH:=$(shell uname -m) +PATH_SEP = : +ifeq ($(LP64), 1) + ARCH_DATA_MODEL ?= 64 +else + ARCH_DATA_MODEL ?= 32 +endif + +ifeq ($(ARCH_DATA_MODEL), 64) + ARCH = ppc64 +else + ARCH = ppc +endif + +# PPC +ifeq ($(ARCH), ppc) + #ARCH_DATA_MODEL = 32 + PLATFORM = aix-ppc + VM_PLATFORM = aix_ppc + HS_ARCH = ppc +endif + +# PPC64 +ifeq ($(ARCH), ppc64) + #ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = aix-ppc64 + VM_PLATFORM = aix_ppc64 + HS_ARCH = ppc +endif + +# On 32 bit aix we build server and client, on 64 bit just server. +ifeq ($(JVM_VARIANTS),) + ifeq ($(ARCH_DATA_MODEL), 32) + JVM_VARIANTS:=client,server + JVM_VARIANT_CLIENT:=true + JVM_VARIANT_SERVER:=true + else + JVM_VARIANTS:=server + JVM_VARIANT_SERVER:=true + endif +endif + +# determine if HotSpot is being built in JDK6 or earlier version +JDK6_OR_EARLIER=0 +ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1" + # if the longer variable names (newer build style) are set, then check those + ifeq "$(shell expr \( $(JDK_MAJOR_VERSION) = 1 \& $(JDK_MINOR_VERSION) \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +else + # the longer variables aren't set so check the shorter variable names + ifeq "$(shell expr \( '$(JDK_MAJOR_VER)' = 1 \& '$(JDK_MINOR_VER)' \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +endif + +ifeq ($(JDK6_OR_EARLIER),0) + # Full Debug Symbols is supported on JDK7 or newer. + # The Full Debug Symbols (FDS) default for BUILD_FLAVOR == product + # builds is enabled with debug info files ZIP'ed to save space. For + # BUILD_FLAVOR != product builds, FDS is always enabled, after all a + # debug build without debug info isn't very useful. + # The ZIP_DEBUGINFO_FILES option only has meaning when FDS is enabled. + # + # If you invoke a build with FULL_DEBUG_SYMBOLS=0, then FDS will be + # disabled for a BUILD_FLAVOR == product build. + # + # Note: Use of a different variable name for the FDS override option + # versus the FDS enabled check is intentional (FULL_DEBUG_SYMBOLS + # versus ENABLE_FULL_DEBUG_SYMBOLS). For auto build systems that pass + # in options via environment variables, use of distinct variables + # prevents strange behaviours. For example, in a BUILD_FLAVOR != + # product build, the FULL_DEBUG_SYMBOLS environment variable will be + # 0, but the ENABLE_FULL_DEBUG_SYMBOLS make variable will be 1. If + # the same variable name is used, then different values can be picked + # up by different parts of the build. Just to be clear, we only need + # two variable names because the incoming option value can be + # overridden in some situations, e.g., a BUILD_FLAVOR != product + # build. + + # Due to the multiple sub-make processes that occur this logic gets + # executed multiple times. We reduce the noise by at least checking that + # BUILD_FLAVOR has been set. + ifneq ($(BUILD_FLAVOR),) + ifeq ($(BUILD_FLAVOR), product) + FULL_DEBUG_SYMBOLS ?= 1 + ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS) + else + # debug variants always get Full Debug Symbols (if available) + ENABLE_FULL_DEBUG_SYMBOLS = 1 + endif + _JUNK_ := $(shell \ + echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)") + # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later + + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + # Default OBJCOPY comes from GNU Binutils on Linux + ifeq ($(CROSS_COMPILE_ARCH),) + DEF_OBJCOPY=/usr/bin/objcopy + else + # Assume objcopy is part of the cross-compilation toolset + ifneq ($(ALT_COMPILER_PATH),) + DEF_OBJCOPY=$(ALT_COMPILER_PATH)/objcopy + endif + endif + OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY)) + ifneq ($(ALT_OBJCOPY),) + _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)") + OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY)) + endif + + ifeq ($(OBJCOPY),) + _JUNK_ := $(shell \ + echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files. You may need to set ALT_OBJCOPY.") + ENABLE_FULL_DEBUG_SYMBOLS=0 + _JUNK_ := $(shell \ + echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)") + else + _JUNK_ := $(shell \ + echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.") + + # Library stripping policies for .debuginfo configs: + # all_strip - strips everything from the library + # min_strip - strips most stuff from the library; leaves minimum symbols + # no_strip - does not strip the library at all + # + # Oracle security policy requires "all_strip". A waiver was granted on + # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE. + # + # Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled. + # + STRIP_POLICY ?= min_strip + + _JUNK_ := $(shell \ + echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)") + + ZIP_DEBUGINFO_FILES ?= 1 + + _JUNK_ := $(shell \ + echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)") + endif + endif # ENABLE_FULL_DEBUG_SYMBOLS=1 + endif # BUILD_FLAVOR +endif # JDK_6_OR_EARLIER + +# unused JDK_INCLUDE_SUBDIR=aix + +# Library suffix +LIBRARY_SUFFIX=so + +EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html + +# client and server subdirectories have symbolic links to ../libjsig.so +EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) +#ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) +# ifeq ($(ZIP_DEBUGINFO_FILES),1) +# EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.diz +# else +# EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo +# endif +#endif +EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server +EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client +EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal + +ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK) $(JVM_VARIANT_CORE)), true) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) +# ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) +# ifeq ($(ZIP_DEBUGINFO_FILES),1) +# EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.diz +# else +# EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo +# endif +# endif +endif + +ifeq ($(JVM_VARIANT_CLIENT),true) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) +# ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) +# ifeq ($(ZIP_DEBUGINFO_FILES),1) +# EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz +# else +# EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo +# endif +# endif +endif + +# Serviceability Binaries +# No SA Support for PPC or zero +ADD_SA_BINARIES/ppc = +ADD_SA_BINARIES/ppc64 = +ADD_SA_BINARIES/zero = + +EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH)) + + diff --git a/hotspot/make/aix/makefiles/dtrace.make b/hotspot/make/aix/makefiles/dtrace.make new file mode 100644 index 00000000000..749877d4aee --- /dev/null +++ b/hotspot/make/aix/makefiles/dtrace.make @@ -0,0 +1,27 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Linux does not build jvm_db +LIBJVM_DB = + diff --git a/hotspot/make/aix/makefiles/fastdebug.make b/hotspot/make/aix/makefiles/fastdebug.make new file mode 100644 index 00000000000..40d792002e6 --- /dev/null +++ b/hotspot/make/aix/makefiles/fastdebug.make @@ -0,0 +1,73 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Sets make macros for making debug version of VM + +# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make +# Pare down optimization to -O2 if xlCV10.1 is in use. +OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS) $(QV10_OPT_CONSERVATIVE) +OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) + +# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) + +ifeq ($(BUILDARCH), ia64) + # Bug in GCC, causes hang. -O1 will override the -O3 specified earlier + OPT_CFLAGS/callGenerator.o += -O1 + OPT_CFLAGS/ciTypeFlow.o += -O1 + OPT_CFLAGS/compile.o += -O1 + OPT_CFLAGS/concurrentMarkSweepGeneration.o += -O1 + OPT_CFLAGS/doCall.o += -O1 + OPT_CFLAGS/generateOopMap.o += -O1 + OPT_CFLAGS/generateOptoStub.o += -O1 + OPT_CFLAGS/graphKit.o += -O1 + OPT_CFLAGS/instanceKlass.o += -O1 + OPT_CFLAGS/interpreterRT_ia64.o += -O1 + OPT_CFLAGS/output.o += -O1 + OPT_CFLAGS/parse1.o += -O1 + OPT_CFLAGS/runtime.o += -O1 + OPT_CFLAGS/synchronizer.o += -O1 +endif + + +# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings +CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/aix/makefiles/mapfile-vers-debug + +# xlc 10.1 parameters for ipa linkage. +# - remove ipa linkage altogether. Does not seem to benefit performance, +# but increases code footprint. +# - this is a debug build in the end. Extra effort for ipa linkage is thus +# not justified. +LFLAGS_QIPA= + +G_SUFFIX = _g +VERSION = optimized +SYSDEFS += -DASSERT -DFASTDEBUG +PICFLAGS = DEFAULT diff --git a/hotspot/make/aix/makefiles/jsig.make b/hotspot/make/aix/makefiles/jsig.make new file mode 100644 index 00000000000..301aa84195b --- /dev/null +++ b/hotspot/make/aix/makefiles/jsig.make @@ -0,0 +1,87 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Rules to build signal interposition library, used by vm.make + +# libjsig.so: signal interposition library +JSIG = jsig +LIBJSIG = lib$(JSIG).so + +LIBJSIG_DEBUGINFO = lib$(JSIG).debuginfo +LIBJSIG_DIZ = lib$(JSIG).diz + +JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm + +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO) +DEST_JSIG_DIZ = $(JDK_LIBDIR)/$(LIBJSIG_DIZ) + +LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig + +# On Linux we really dont want a mapfile, as this library is small +# and preloaded using LD_PRELOAD, making functions private will +# cause problems with interposing. See CR: 6466665 +# LFLAGS_JSIG += $(MAPFLAG:FILENAME=$(LIBJSIG_MAPFILE)) + +LFLAGS_JSIG += -D_GNU_SOURCE -D_REENTRANT $(LDFLAGS_HASH_STYLE) + +LFLAGS_JSIG += $(BIN_UTILS) + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + JSIG_DEBUG_CFLAGS = -g +endif + +$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE) + @echo Making signal interposition lib... + $(QUIETLY) $(CXX) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ + $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl + +#ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) +# $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) +# $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ +# ifeq ($(STRIP_POLICY),all_strip) +# $(QUIETLY) $(STRIP) $@ +# else +# ifeq ($(STRIP_POLICY),min_strip) +# $(QUIETLY) $(STRIP) -g $@ +# # implied else here is no stripping at all +# endif +# endif +# ifeq ($(ZIP_DEBUGINFO_FILES),1) +# $(ZIPEXE) -q -y $(LIBJSIG_DIZ) $(LIBJSIG_DEBUGINFO) +# $(RM) $(LIBJSIG_DEBUGINFO) +# endif +#endif + +install_jsig: $(LIBJSIG) + @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) + $(QUIETLY) test -f $(LIBJSIG_DIZ) && \ + cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ) + $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" + +.PHONY: install_jsig diff --git a/hotspot/make/aix/makefiles/jvmti.make b/hotspot/make/aix/makefiles/jvmti.make new file mode 100644 index 00000000000..6baf4d31c66 --- /dev/null +++ b/hotspot/make/aix/makefiles/jvmti.make @@ -0,0 +1,118 @@ +# +# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 makefile (jvmti.make) is included from the jvmti.make in the +# build directories. +# +# It knows how to build and run the tools to generate jvmti. + +include $(GAMMADIR)/make/aix/makefiles/rules.make + +# ######################################################################### + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles + +JvmtiSrcDir = $(GAMMADIR)/src/share/vm/prims +InterpreterSrcDir = $(GAMMADIR)/src/share/vm/interpreter + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(JvmtiSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +JvmtiGeneratedNames = \ + jvmtiEnv.hpp \ + jvmtiEnter.cpp \ + jvmtiEnterTrace.cpp \ + jvmtiEnvRecommended.cpp \ + bytecodeInterpreterWithChecks.cpp \ + jvmti.h \ + +JvmtiEnvFillSource = $(JvmtiSrcDir)/jvmtiEnvFill.java +JvmtiEnvFillClass = $(JvmtiOutDir)/jvmtiEnvFill.class + +JvmtiGenSource = $(JvmtiSrcDir)/jvmtiGen.java +JvmtiGenClass = $(JvmtiOutDir)/jvmtiGen.class + +JvmtiGeneratedFiles = $(JvmtiGeneratedNames:%=$(JvmtiOutDir)/%) + +XSLT = $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +.PHONY: all jvmtidocs clean cleanall + +# ######################################################################### + +all: $(JvmtiGeneratedFiles) + +both = $(JvmtiGenClass) $(JvmtiSrcDir)/jvmti.xml $(JvmtiSrcDir)/jvmtiLib.xsl + +$(JvmtiGenClass): $(JvmtiGenSource) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource) + +$(JvmtiEnvFillClass): $(JvmtiEnvFillSource) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource) + +$(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnter.cpp -PARAM interface jvmti + +$(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp: $(JvmtiGenClass) $(InterpreterSrcDir)/bytecodeInterpreter.cpp $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl + @echo Generating $@ + $(XSLT) -IN $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml -XSL $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl -OUT $(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp + +$(JvmtiOutDir)/jvmtiEnterTrace.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnterTrace.cpp -PARAM interface jvmti -PARAM trace Trace + +$(JvmtiOutDir)/jvmtiEnvRecommended.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnv.xsl $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiEnvFillClass) + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnv.xsl -OUT $(JvmtiOutDir)/jvmtiEnvStub.cpp + $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiEnvFill $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiOutDir)/jvmtiEnvStub.cpp $(JvmtiOutDir)/jvmtiEnvRecommended.cpp + +$(JvmtiOutDir)/jvmtiEnv.hpp: $(both) $(JvmtiSrcDir)/jvmtiHpp.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiHpp.xsl -OUT $(JvmtiOutDir)/jvmtiEnv.hpp + +$(JvmtiOutDir)/jvmti.h: $(both) $(JvmtiSrcDir)/jvmtiH.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiH.xsl -OUT $(JvmtiOutDir)/jvmti.h + +jvmtidocs: $(JvmtiOutDir)/jvmti.html + +$(JvmtiOutDir)/jvmti.html: $(both) $(JvmtiSrcDir)/jvmti.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmti.xsl -OUT $(JvmtiOutDir)/jvmti.html + +# ######################################################################### + +clean : + rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles) + +cleanall : + rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles) + +# ######################################################################### + diff --git a/hotspot/make/aix/makefiles/mapfile-vers-debug b/hotspot/make/aix/makefiles/mapfile-vers-debug new file mode 100644 index 00000000000..b18fb74fd9a --- /dev/null +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug @@ -0,0 +1,274 @@ +# +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + # JNI + JNI_CreateJavaVM; + JNI_GetCreatedJavaVMs; + JNI_GetDefaultJavaVMInitArgs; + + # JVM + JVM_Accept; + JVM_ActiveProcessorCount; + JVM_AllocateNewArray; + JVM_AllocateNewObject; + JVM_ArrayCopy; + JVM_AssertionStatusDirectives; + JVM_Available; + JVM_Bind; + JVM_ClassDepth; + JVM_ClassLoaderDepth; + JVM_Clone; + JVM_Close; + JVM_CX8Field; + JVM_CompileClass; + JVM_CompileClasses; + JVM_CompilerCommand; + JVM_Connect; + JVM_ConstantPoolGetClassAt; + JVM_ConstantPoolGetClassAtIfLoaded; + JVM_ConstantPoolGetDoubleAt; + JVM_ConstantPoolGetFieldAt; + JVM_ConstantPoolGetFieldAtIfLoaded; + JVM_ConstantPoolGetFloatAt; + JVM_ConstantPoolGetIntAt; + JVM_ConstantPoolGetLongAt; + JVM_ConstantPoolGetMethodAt; + JVM_ConstantPoolGetMethodAtIfLoaded; + JVM_ConstantPoolGetMemberRefInfoAt; + JVM_ConstantPoolGetSize; + JVM_ConstantPoolGetStringAt; + JVM_ConstantPoolGetUTF8At; + JVM_CountStackFrames; + JVM_CurrentClassLoader; + JVM_CurrentLoadedClass; + JVM_CurrentThread; + JVM_CurrentTimeMillis; + JVM_DefineClass; + JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; + JVM_DesiredAssertionStatus; + JVM_DisableCompiler; + JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; + JVM_DumpAllStacks; + JVM_DumpThreads; + JVM_EnableCompiler; + JVM_Exit; + JVM_FillInStackTrace; + JVM_FindClassFromClass; + JVM_FindClassFromClassLoader; + JVM_FindClassFromBootLoader; + JVM_FindLibraryEntry; + JVM_FindLoadedClass; + JVM_FindPrimitiveClass; + JVM_FindSignal; + JVM_FreeMemory; + JVM_GC; + JVM_GetAllThreads; + JVM_GetArrayElement; + JVM_GetArrayLength; + JVM_GetCPClassNameUTF; + JVM_GetCPFieldClassNameUTF; + JVM_GetCPFieldModifiers; + JVM_GetCPFieldNameUTF; + JVM_GetCPFieldSignatureUTF; + JVM_GetCPMethodClassNameUTF; + JVM_GetCPMethodModifiers; + JVM_GetCPMethodNameUTF; + JVM_GetCPMethodSignatureUTF; + JVM_GetCallerClass; + JVM_GetClassAccessFlags; + JVM_GetClassAnnotations; + JVM_GetClassCPEntriesCount; + JVM_GetClassCPTypes; + JVM_GetClassConstantPool; + JVM_GetClassContext; + JVM_GetClassDeclaredConstructors; + JVM_GetClassDeclaredFields; + JVM_GetClassDeclaredMethods; + JVM_GetClassFieldsCount; + JVM_GetClassInterfaces; + JVM_GetClassLoader; + JVM_GetClassMethodsCount; + JVM_GetClassModifiers; + JVM_GetClassName; + JVM_GetClassNameUTF; + JVM_GetClassSignature; + JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; + JVM_GetComponentType; + JVM_GetDeclaredClasses; + JVM_GetDeclaringClass; + JVM_GetEnclosingMethodInfo; + JVM_GetFieldAnnotations; + JVM_GetFieldIxModifiers; + JVM_GetFieldTypeAnnotations; + JVM_GetHostName; + JVM_GetInheritedAccessControlContext; + JVM_GetInterfaceVersion; + JVM_GetLastErrorString; + JVM_GetManagement; + JVM_GetMethodAnnotations; + JVM_GetMethodDefaultAnnotationValue; + JVM_GetMethodIxArgsSize; + JVM_GetMethodIxByteCode; + JVM_GetMethodIxByteCodeLength; + JVM_GetMethodIxExceptionIndexes; + JVM_GetMethodIxExceptionTableEntry; + JVM_GetMethodIxExceptionTableLength; + JVM_GetMethodIxExceptionsCount; + JVM_GetMethodIxLocalsCount; + JVM_GetMethodIxMaxStack; + JVM_GetMethodIxModifiers; + JVM_GetMethodIxNameUTF; + JVM_GetMethodIxSignatureUTF; + JVM_GetMethodParameterAnnotations; + JVM_GetMethodParameters; + JVM_GetMethodTypeAnnotations; + JVM_GetPrimitiveArrayElement; + JVM_GetProtectionDomain; + JVM_GetSockName; + JVM_GetSockOpt; + JVM_GetStackAccessControlContext; + JVM_GetStackTraceDepth; + JVM_GetStackTraceElement; + JVM_GetSystemPackage; + JVM_GetSystemPackages; + JVM_GetThreadStateNames; + JVM_GetThreadStateValues; + JVM_GetVersionInfo; + JVM_Halt; + JVM_HoldsLock; + JVM_IHashCode; + JVM_InitAgentProperties; + JVM_InitProperties; + JVM_InitializeCompiler; + JVM_InitializeSocketLibrary; + JVM_InternString; + JVM_Interrupt; + JVM_InvokeMethod; + JVM_IsArrayClass; + JVM_IsConstructorIx; + JVM_IsInterface; + JVM_IsInterrupted; + JVM_IsNaN; + JVM_IsPrimitiveClass; + JVM_IsSameClassPackage; + JVM_IsSilentCompiler; + JVM_IsSupportedJNIVersion; + JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; + JVM_LatestUserDefinedLoader; + JVM_Listen; + JVM_LoadClass0; + JVM_LoadLibrary; + JVM_Lseek; + JVM_MaxObjectInspectionAge; + JVM_MaxMemory; + JVM_MonitorNotify; + JVM_MonitorNotifyAll; + JVM_MonitorWait; + JVM_NanoTime; + JVM_NativePath; + JVM_NewArray; + JVM_NewInstanceFromConstructor; + JVM_NewMultiArray; + JVM_OnExit; + JVM_Open; + JVM_RaiseSignal; + JVM_RawMonitorCreate; + JVM_RawMonitorDestroy; + JVM_RawMonitorEnter; + JVM_RawMonitorExit; + JVM_Read; + JVM_Recv; + JVM_RecvFrom; + JVM_RegisterSignal; + JVM_ReleaseUTF; + JVM_ResolveClass; + JVM_ResumeThread; + JVM_Send; + JVM_SendTo; + JVM_SetArrayElement; + JVM_SetClassSigners; + JVM_SetLength; + JVM_SetNativeThreadName; + JVM_SetPrimitiveArrayElement; + JVM_SetProtectionDomain; + JVM_SetSockOpt; + JVM_SetThreadPriority; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; + JVM_SocketClose; + JVM_SocketShutdown; + JVM_StartThread; + JVM_StopThread; + JVM_SuspendThread; + JVM_SupportsCX8; + JVM_Sync; + JVM_Timeout; + JVM_TotalMemory; + JVM_TraceInstructions; + JVM_TraceMethodCalls; + JVM_UnloadLibrary; + JVM_Write; + JVM_Yield; + JVM_handle_linux_signal; + + # debug JVM + JVM_AccessVMBooleanFlag; + JVM_AccessVMIntFlag; + JVM_VMBreakPoint; + + # miscellaneous functions + jio_fprintf; + jio_printf; + jio_snprintf; + jio_vfprintf; + jio_vsnprintf; + fork1; + numa_warn; + numa_error; + + # Needed because there is no JVM interface for this. + sysThreadAvailableStackWithSlack; + + # This is for Forte Analyzer profiling support. + AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + + local: + *; +}; + diff --git a/hotspot/make/aix/makefiles/mapfile-vers-jsig b/hotspot/make/aix/makefiles/mapfile-vers-jsig new file mode 100644 index 00000000000..ddb46c050ec --- /dev/null +++ b/hotspot/make/aix/makefiles/mapfile-vers-jsig @@ -0,0 +1,38 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + JVM_begin_signal_setting; + JVM_end_signal_setting; + JVM_get_libjsig_version; + JVM_get_signal_action; + sigaction; + signal; + sigset; + local: + *; +}; diff --git a/hotspot/make/aix/makefiles/mapfile-vers-product b/hotspot/make/aix/makefiles/mapfile-vers-product new file mode 100644 index 00000000000..04531fa15aa --- /dev/null +++ b/hotspot/make/aix/makefiles/mapfile-vers-product @@ -0,0 +1,267 @@ +# +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + # JNI + JNI_CreateJavaVM; + JNI_GetCreatedJavaVMs; + JNI_GetDefaultJavaVMInitArgs; + + # JVM + JVM_Accept; + JVM_ActiveProcessorCount; + JVM_AllocateNewArray; + JVM_AllocateNewObject; + JVM_ArrayCopy; + JVM_AssertionStatusDirectives; + JVM_Available; + JVM_Bind; + JVM_ClassDepth; + JVM_ClassLoaderDepth; + JVM_Clone; + JVM_Close; + JVM_CX8Field; + JVM_CompileClass; + JVM_CompileClasses; + JVM_CompilerCommand; + JVM_Connect; + JVM_ConstantPoolGetClassAt; + JVM_ConstantPoolGetClassAtIfLoaded; + JVM_ConstantPoolGetDoubleAt; + JVM_ConstantPoolGetFieldAt; + JVM_ConstantPoolGetFieldAtIfLoaded; + JVM_ConstantPoolGetFloatAt; + JVM_ConstantPoolGetIntAt; + JVM_ConstantPoolGetLongAt; + JVM_ConstantPoolGetMethodAt; + JVM_ConstantPoolGetMethodAtIfLoaded; + JVM_ConstantPoolGetMemberRefInfoAt; + JVM_ConstantPoolGetSize; + JVM_ConstantPoolGetStringAt; + JVM_ConstantPoolGetUTF8At; + JVM_CountStackFrames; + JVM_CurrentClassLoader; + JVM_CurrentLoadedClass; + JVM_CurrentThread; + JVM_CurrentTimeMillis; + JVM_DefineClass; + JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; + JVM_DesiredAssertionStatus; + JVM_DisableCompiler; + JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; + JVM_DumpAllStacks; + JVM_DumpThreads; + JVM_EnableCompiler; + JVM_Exit; + JVM_FillInStackTrace; + JVM_FindClassFromClass; + JVM_FindClassFromClassLoader; + JVM_FindClassFromBootLoader; + JVM_FindLibraryEntry; + JVM_FindLoadedClass; + JVM_FindPrimitiveClass; + JVM_FindSignal; + JVM_FreeMemory; + JVM_GC; + JVM_GetAllThreads; + JVM_GetArrayElement; + JVM_GetArrayLength; + JVM_GetCPClassNameUTF; + JVM_GetCPFieldClassNameUTF; + JVM_GetCPFieldModifiers; + JVM_GetCPFieldNameUTF; + JVM_GetCPFieldSignatureUTF; + JVM_GetCPMethodClassNameUTF; + JVM_GetCPMethodModifiers; + JVM_GetCPMethodNameUTF; + JVM_GetCPMethodSignatureUTF; + JVM_GetCallerClass; + JVM_GetClassAccessFlags; + JVM_GetClassAnnotations; + JVM_GetClassCPEntriesCount; + JVM_GetClassCPTypes; + JVM_GetClassConstantPool; + JVM_GetClassContext; + JVM_GetClassDeclaredConstructors; + JVM_GetClassDeclaredFields; + JVM_GetClassDeclaredMethods; + JVM_GetClassFieldsCount; + JVM_GetClassInterfaces; + JVM_GetClassLoader; + JVM_GetClassMethodsCount; + JVM_GetClassModifiers; + JVM_GetClassName; + JVM_GetClassNameUTF; + JVM_GetClassSignature; + JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; + JVM_GetComponentType; + JVM_GetDeclaredClasses; + JVM_GetDeclaringClass; + JVM_GetEnclosingMethodInfo; + JVM_GetFieldAnnotations; + JVM_GetFieldIxModifiers; + JVM_GetHostName; + JVM_GetInheritedAccessControlContext; + JVM_GetInterfaceVersion; + JVM_GetLastErrorString; + JVM_GetManagement; + JVM_GetMethodAnnotations; + JVM_GetMethodDefaultAnnotationValue; + JVM_GetMethodIxArgsSize; + JVM_GetMethodIxByteCode; + JVM_GetMethodIxByteCodeLength; + JVM_GetMethodIxExceptionIndexes; + JVM_GetMethodIxExceptionTableEntry; + JVM_GetMethodIxExceptionTableLength; + JVM_GetMethodIxExceptionsCount; + JVM_GetMethodIxLocalsCount; + JVM_GetMethodIxMaxStack; + JVM_GetMethodIxModifiers; + JVM_GetMethodIxNameUTF; + JVM_GetMethodIxSignatureUTF; + JVM_GetMethodParameterAnnotations; + JVM_GetMethodParameters; + JVM_GetPrimitiveArrayElement; + JVM_GetProtectionDomain; + JVM_GetSockName; + JVM_GetSockOpt; + JVM_GetStackAccessControlContext; + JVM_GetStackTraceDepth; + JVM_GetStackTraceElement; + JVM_GetSystemPackage; + JVM_GetSystemPackages; + JVM_GetThreadStateNames; + JVM_GetThreadStateValues; + JVM_GetVersionInfo; + JVM_Halt; + JVM_HoldsLock; + JVM_IHashCode; + JVM_InitAgentProperties; + JVM_InitProperties; + JVM_InitializeCompiler; + JVM_InitializeSocketLibrary; + JVM_InternString; + JVM_Interrupt; + JVM_InvokeMethod; + JVM_IsArrayClass; + JVM_IsConstructorIx; + JVM_IsInterface; + JVM_IsInterrupted; + JVM_IsNaN; + JVM_IsPrimitiveClass; + JVM_IsSameClassPackage; + JVM_IsSilentCompiler; + JVM_IsSupportedJNIVersion; + JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; + JVM_LatestUserDefinedLoader; + JVM_Listen; + JVM_LoadClass0; + JVM_LoadLibrary; + JVM_Lseek; + JVM_MaxObjectInspectionAge; + JVM_MaxMemory; + JVM_MonitorNotify; + JVM_MonitorNotifyAll; + JVM_MonitorWait; + JVM_NanoTime; + JVM_NativePath; + JVM_NewArray; + JVM_NewInstanceFromConstructor; + JVM_NewMultiArray; + JVM_OnExit; + JVM_Open; + JVM_RaiseSignal; + JVM_RawMonitorCreate; + JVM_RawMonitorDestroy; + JVM_RawMonitorEnter; + JVM_RawMonitorExit; + JVM_Read; + JVM_Recv; + JVM_RecvFrom; + JVM_RegisterSignal; + JVM_ReleaseUTF; + JVM_ResolveClass; + JVM_ResumeThread; + JVM_Send; + JVM_SendTo; + JVM_SetArrayElement; + JVM_SetClassSigners; + JVM_SetLength; + JVM_SetNativeThreadName; + JVM_SetPrimitiveArrayElement; + JVM_SetProtectionDomain; + JVM_SetSockOpt; + JVM_SetThreadPriority; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; + JVM_SocketClose; + JVM_SocketShutdown; + JVM_StartThread; + JVM_StopThread; + JVM_SuspendThread; + JVM_SupportsCX8; + JVM_Sync; + JVM_Timeout; + JVM_TotalMemory; + JVM_TraceInstructions; + JVM_TraceMethodCalls; + JVM_UnloadLibrary; + JVM_Write; + JVM_Yield; + JVM_handle_linux_signal; + + # miscellaneous functions + jio_fprintf; + jio_printf; + jio_snprintf; + jio_vfprintf; + jio_vsnprintf; + fork1; + numa_warn; + numa_error; + + # Needed because there is no JVM interface for this. + sysThreadAvailableStackWithSlack; + + # This is for Forte Analyzer profiling support. + AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + + local: + *; +}; + diff --git a/hotspot/make/aix/makefiles/ppc64.make b/hotspot/make/aix/makefiles/ppc64.make new file mode 100644 index 00000000000..079d0764769 --- /dev/null +++ b/hotspot/make/aix/makefiles/ppc64.make @@ -0,0 +1,94 @@ +# +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Produce 64 bits object files. +CFLAGS += -q64 + +# Balanced tuning for recent versions of the POWER architecture (if supported by xlc). +QTUNE=$(if $(CXX_SUPPORTS_BALANCED_TUNING),balanced,pwr5) + +# Try to speed up the interpreter: use ppc64 instructions and inline +# glue code for external functions. +OPT_CFLAGS += -qarch=ppc64 -qtune=$(QTUNE) -qinlglue + +# We need variable length arrays +CFLAGS += -qlanglvl=c99vla +# Just to check for unwanted macro redefinitions +CFLAGS += -qlanglvl=noredefmac + +# Suppress those "implicit private" warnings xlc gives. +# - The omitted keyword "private" is assumed for base class "...". +CFLAGS += -qsuppress=1540-0198 + +# Suppress the following numerous warning: +# - 1540-1090 (I) The destructor of "..." might not be called. +# - 1500-010: (W) WARNING in ...: Infinite loop. Program may not stop. +# There are several infinite loops in the vm, suppress. +CFLAGS += -qsuppress=1540-1090 -qsuppress=1500-010 + +# Suppress +# - 540-1088 (W) The exception specification is being ignored. +# caused by throw() in declaration of new() in nmethod.hpp. +CFLAGS += -qsuppress=1540-1088 + +# Turn off floating-point optimizations that may alter program semantics +OPT_CFLAGS += -qstrict + +# Disable aggressive optimizations for functions in sharedRuntimeTrig.cpp +# and sharedRuntimeTrans.cpp on ppc64. +# -qstrict turns off the following optimizations: +# * Performing code motion and scheduling on computations such as loads +# and floating-point computations that may trigger an exception. +# * Relaxing conformance to IEEE rules. +# * Reassociating floating-point expressions. +# When using '-qstrict' there still remains one problem +# in javasoft.sqe.tests.api.java.lang.Math.sin5Tests when run in compile-all +# mode, so don't optimize sharedRuntimeTrig.cpp at all. +OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) +OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) + +# xlc 10.01 parameters for ipa compile. +QIPA_COMPILE=$(if $(CXX_IS_V10),-qipa) + +# Xlc 10.1 parameters for aggressive optimization: +# - qhot=level=1: Most aggressive loop optimizations. +# - qignerrno: Assume errno is not modified by system calls. +# - qinline: Inline method calls. No suboptions for c++ compiles. +# - qxflag=ASMMIDCOALFIX: Activate fix for -O3 problem in interpreter loop. +# - qxflag=asmfastsync: Activate fix for performance problem with inline assembler with memory clobber. +QV10_OPT=$(if $(CXX_IS_V10),-qxflag=ASMMIDCOALFIX -qxflag=asmfastsync) +QV10_OPT_AGGRESSIVE=$(if $(CXX_IS_V10),-qhot=level=1 -qignerrno -qinline) +QV10_OPT_CONSERVATIVE=$(if $(CXX_IS_V10),-qhot=level=1 -qignerrno -qinline) + +# Disallow inlining for synchronizer.cpp, but perform O3 optimizations. +OPT_CFLAGS/synchronizer.o = $(OPT_CFLAGS) -qnoinline + +# Set all the xlC V10.1 options here. +OPT_CFLAGS += $(QIPA_COMPILE) $(QV10_OPT) $(QV10_OPT_AGGRESSIVE) + +export OBJECT_MODE=64 + +# Also build launcher as 64 bit executable. +LAUNCHERFLAGS += -q64 diff --git a/hotspot/make/aix/makefiles/product.make b/hotspot/make/aix/makefiles/product.make new file mode 100644 index 00000000000..f1ef85a8192 --- /dev/null +++ b/hotspot/make/aix/makefiles/product.make @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Sets make macros for making optimized version of Gamma VM +# (This is the "product", not the "release" version.) + +# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make +OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS) +OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) + +# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) + +# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings +CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/aix/makefiles/mapfile-vers-product + +# Remove ipa linkage altogether. Does not seem to benfit performance, but increases code footprint. +LFLAGS_QIPA= + +SYSDEFS += -DPRODUCT +VERSION = optimized + +# use -g to strip library as -x will discard its symbol table; -x is fine for +# executables. +# Note: these macros are not used in .debuginfo configs +STRIP_LIBJVM = $(STRIP) -g $@ || exit 1; +STRIP_AOUT = $(STRIP) -x $@ || exit 1; + +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. +# LINK_LIB.CXX/POST_HOOK += $(STRIP_$(LINK_INTO)) diff --git a/hotspot/make/aix/makefiles/rules.make b/hotspot/make/aix/makefiles/rules.make new file mode 100644 index 00000000000..33898f5c858 --- /dev/null +++ b/hotspot/make/aix/makefiles/rules.make @@ -0,0 +1,203 @@ +# +# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Common rules/macros for the vm, adlc. + +# Tell make that .cpp is important +.SUFFIXES: .cpp $(SUFFIXES) + +DEMANGLER = c++filt +DEMANGLE = $(DEMANGLER) < $@ > .$@ && mv -f .$@ $@ + +# $(CC) is the c compiler (cc/gcc), $(CXX) is the c++ compiler (CC/g++). +CC_COMPILE = $(CC) $(CXXFLAGS) $(CFLAGS) +CXX_COMPILE = $(CXX) $(CXXFLAGS) $(CFLAGS) + +AS.S = $(AS) $(ASFLAGS) + +COMPILE.CC = $(CC_COMPILE) -c +GENASM.CC = $(CC_COMPILE) -S +LINK.CC = $(CC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS) +LINK_LIB.CC = $(CC) $(LFLAGS) $(SHARED_FLAG) +PREPROCESS.CC = $(CC_COMPILE) -E + +COMPILE.CXX = $(CXX_COMPILE) -c +GENASM.CXX = $(CXX_COMPILE) -S +LINK.CXX = $(CXX) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS) +LINK_NOPROF.CXX = $(CXX) $(LFLAGS) $(AOUT_FLAGS) +LINK_LIB.CXX = $(CXX) $(LFLAGS) $(SHARED_FLAG) +PREPROCESS.CXX = $(CXX_COMPILE) -E + +# cross compiling the jvm with c2 requires host compilers to build +# adlc tool + +HOST.CXX_COMPILE = $(HOSTCXX) $(CXXFLAGS) $(CFLAGS) +HOST.COMPILE.CXX = $(HOST.CXX_COMPILE) -c +HOST.LINK_NOPROF.CXX = $(HOSTCXX) $(LFLAGS) $(AOUT_FLAGS) + + +# Effect of REMOVE_TARGET is to delete out-of-date files during "gnumake -k". +REMOVE_TARGET = rm -f $@ + +# Note use of ALT_BOOTDIR to explicitly specify location of java and +# javac; this is the same environment variable used in the J2SE build +# process for overriding the default spec, which is BOOTDIR. +# Note also that we fall back to using JAVA_HOME if neither of these is +# specified. + +ifdef ALT_BOOTDIR + +RUN.JAVA = $(ALT_BOOTDIR)/bin/java +RUN.JAVAP = $(ALT_BOOTDIR)/bin/javap +RUN.JAVAH = $(ALT_BOOTDIR)/bin/javah +RUN.JAR = $(ALT_BOOTDIR)/bin/jar +COMPILE.JAVAC = $(ALT_BOOTDIR)/bin/javac +COMPILE.RMIC = $(ALT_BOOTDIR)/bin/rmic +BOOT_JAVA_HOME = $(ALT_BOOTDIR) + +else + +ifdef BOOTDIR + +RUN.JAVA = $(BOOTDIR)/bin/java +RUN.JAVAP = $(BOOTDIR)/bin/javap +RUN.JAVAH = $(BOOTDIR)/bin/javah +RUN.JAR = $(BOOTDIR)/bin/jar +COMPILE.JAVAC = $(BOOTDIR)/bin/javac +COMPILE.RMIC = $(BOOTDIR)/bin/rmic +BOOT_JAVA_HOME = $(BOOTDIR) + +else + +ifdef JAVA_HOME + +RUN.JAVA = $(JAVA_HOME)/bin/java +RUN.JAVAP = $(JAVA_HOME)/bin/javap +RUN.JAVAH = $(JAVA_HOME)/bin/javah +RUN.JAR = $(JAVA_HOME)/bin/jar +COMPILE.JAVAC = $(JAVA_HOME)/bin/javac +COMPILE.RMIC = $(JAVA_HOME)/bin/rmic +BOOT_JAVA_HOME = $(JAVA_HOME) + +else + +# take from the PATH, if ALT_BOOTDIR, BOOTDIR and JAVA_HOME are not defined +# note that this is to support hotspot build without SA. To build +# SA along with hotspot, you need to define ALT_BOOTDIR, BOOTDIR or JAVA_HOME + +RUN.JAVA = java +RUN.JAVAP = javap +RUN.JAVAH = javah +RUN.JAR = jar +COMPILE.JAVAC = javac +COMPILE.RMIC = rmic + +endif +endif +endif + +COMPILE.JAVAC += $(BOOTSTRAP_JAVAC_FLAGS) + +SUM = /usr/bin/sum + +# 'gmake MAKE_VERBOSE=y' gives all the gory details. +QUIETLY$(MAKE_VERBOSE) = @ +RUN.JAR$(MAKE_VERBOSE) += >/dev/null + +# Settings for javac +BOOT_SOURCE_LANGUAGE_VERSION = 6 +BOOT_TARGET_CLASS_VERSION = 6 +JAVAC_FLAGS = -g -encoding ascii +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# With parallel makes, print a message at the end of compilation. +ifeq ($(findstring j,$(MFLAGS)),j) +COMPILE_DONE = && { echo Done with $<; } +endif + +# Include $(NONPIC_OBJ_FILES) definition +ifndef LP64 +include $(GAMMADIR)/make/pic.make +endif + +include $(GAMMADIR)/make/altsrc.make + +# The non-PIC object files are only generated for 32 bit platforms. +ifdef LP64 +%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(COMPILE.CXX) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) +else +%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(if $(findstring $@, $(NONPIC_OBJ_FILES)), \ + $(subst $(VM_PICFLAG), ,$(COMPILE.CXX)) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE), \ + $(COMPILE.CXX) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE)) +endif + +%.o: %.s + @echo Assembling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) + +%.s: %.cpp + @echo Generating assembly for $< + $(QUIETLY) $(GENASM.CXX) -o $@ $< + $(QUIETLY) $(DEMANGLE) $(COMPILE_DONE) + +# Intermediate files (for debugging macros) +%.i: %.cpp + @echo Preprocessing $< to $@ + $(QUIETLY) $(PREPROCESS.CXX) $< > $@ $(COMPILE_DONE) + +# Override gnumake built-in rules which do sccs get operations badly. +# (They put the checked out code in the current directory, not in the +# directory of the original file.) Since this is a symptom of a teamware +# failure, and since not all problems can be detected by gnumake due +# to incomplete dependency checking... just complain and stop. +%:: s.% + @echo "=========================================================" + @echo File $@ + @echo is out of date with respect to its SCCS file. + @echo This file may be from an unresolved Teamware conflict. + @echo This is also a symptom of a Teamware bringover/putback failure + @echo in which SCCS files are updated but not checked out. + @echo Check for other out of date files in your workspace. + @echo "=========================================================" + @exit 666 + +%:: SCCS/s.% + @echo "=========================================================" + @echo File $@ + @echo is out of date with respect to its SCCS file. + @echo This file may be from an unresolved Teamware conflict. + @echo This is also a symptom of a Teamware bringover/putback failure + @echo in which SCCS files are updated but not checked out. + @echo Check for other out of date files in your workspace. + @echo "=========================================================" + @exit 666 + +.PHONY: default diff --git a/hotspot/make/aix/makefiles/sa.make b/hotspot/make/aix/makefiles/sa.make new file mode 100644 index 00000000000..b711afb4024 --- /dev/null +++ b/hotspot/make/aix/makefiles/sa.make @@ -0,0 +1,116 @@ +# +# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 makefile (sa.make) is included from the sa.make in the +# build directories. + +# This makefile is used to build Serviceability Agent java code +# and generate JNI header file for native methods. + +include $(GAMMADIR)/make/aix/makefiles/rules.make + +include $(GAMMADIR)/make/defs.make + +AGENT_DIR = $(GAMMADIR)/agent + +include $(GAMMADIR)/make/sa.files + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated + +# tools.jar is needed by the JDI - SA binding +SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar + +# TODO: if it's a modules image, check if SA module is installed. +MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules + +AGENT_FILES_LIST := $(GENERATED)/agent.classes.list + +SA_CLASSDIR = $(GENERATED)/saclasses + +SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION)" + +SA_PROPERTIES = $(SA_CLASSDIR)/sa.properties + +# if $(AGENT_DIR) does not exist, we don't build SA +# also, we don't build SA on Itanium, PowerPC, ARM or zero. + +all: + if [ -d $(AGENT_DIR) -a "$(SRCARCH)" != "ia64" \ + -a "$(SRCARCH)" != "arm" \ + -a "$(SRCARCH)" != "ppc" \ + -a "$(SRCARCH)" != "zero" ] ; then \ + $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \ + fi + +$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) + $(QUIETLY) echo "Making $@" + $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ + echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ + exit 1; \ + fi + $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \ + echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\ + echo ""; \ + exit 1; \ + fi + $(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \ + mkdir -p $(SA_CLASSDIR); \ + fi +# Note: When indented, make tries to execute the '$(shell' comment. +# In some environments, cmd processors have limited line length. +# To prevent the javac invocation in the next block from using +# a very long cmd line, we use javac's @file-list option. We +# generate the file lists using make's built-in 'foreach' control +# flow which also avoids cmd processor line length issues. Since +# the 'foreach' is done as part of make's macro expansion phase, +# the initialization of the lists is also done in the same phase +# using '$(shell rm ...' instead of using the more traditional +# 'rm ...' rule. + $(shell rm -rf $(AGENT_FILES_LIST)) +# gnumake 3.78.1 does not accept the *'s that +# are in AGENT_FILES, so use the shell to expand them. +# Be extra carefull to not produce too long command lines in the shell! + $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST))) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST) + $(QUIETLY) $(REMOTE) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer + $(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES) + $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js + $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql + $(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources + $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/* + $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/ + $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/ + $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(SA_CLASSDIR)/ . + $(QUIETLY) $(REMOTE) $(RUN.JAR) uf $@ -C $(AGENT_SRC_DIR) META-INF/services/com.sun.jdi.connect.Connector + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.sparc.SPARCThreadContext + +clean: + rm -rf $(SA_CLASSDIR) + rm -rf $(GENERATED)/sa-jdi.jar + rm -rf $(AGENT_FILES_LIST) diff --git a/hotspot/make/aix/makefiles/saproc.make b/hotspot/make/aix/makefiles/saproc.make new file mode 100644 index 00000000000..a7f28914a3d --- /dev/null +++ b/hotspot/make/aix/makefiles/saproc.make @@ -0,0 +1,117 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 $(GAMMADIR)/make/defs.make + +# Rules to build serviceability agent library, used by vm.make + +# libsaproc.so: serviceability agent + +SAPROC = saproc +LIBSAPROC = lib$(SAPROC).so + +LIBSAPROC_DEBUGINFO = lib$(SAPROC).debuginfo +LIBSAPROC_DIZ = lib$(SAPROC).diz + +AGENT_DIR = $(GAMMADIR)/agent + +SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family) + +SASRCFILES = $(SASRCDIR)/salibelf.c \ + $(SASRCDIR)/symtab.c \ + $(SASRCDIR)/libproc_impl.c \ + $(SASRCDIR)/ps_proc.c \ + $(SASRCDIR)/ps_core.c \ + $(SASRCDIR)/LinuxDebuggerLocal.c \ + +SAMAPFILE = $(SASRCDIR)/mapfile + +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO) +DEST_SAPROC_DIZ = $(JDK_LIBDIR)/$(LIBSAPROC_DIZ) + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + SA_DEBUG_CFLAGS = -g +endif + +# if $(AGENT_DIR) does not exist, we don't build SA +# also, we don't build SA on Itanium, PPC, ARM or zero. + +ifneq ($(wildcard $(AGENT_DIR)),) +ifneq ($(filter-out ia64 arm ppc zero,$(SRCARCH)),) + BUILDLIBSAPROC = $(LIBSAPROC) +endif +endif + + +SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) $(LDFLAGS_HASH_STYLE) + +$(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) + $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ + echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ + exit 1; \ + fi + @echo Making SA debugger back-end... + $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + -D_FILE_OFFSET_BITS=64 \ + $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ + $(BIN_UTILS) \ + -I$(SASRCDIR) \ + -I$(GENERATED) \ + -I$(BOOT_JAVA_HOME)/include \ + -I$(BOOT_JAVA_HOME)/include/$(Platform_os_family) \ + $(SASRCFILES) \ + $(SA_LFLAGS) \ + $(SA_DEBUG_CFLAGS) \ + -o $@ \ + -lthread_db +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + ifeq ($(ZIP_DEBUGINFO_FILES),1) + $(ZIPEXE) -q -y $(LIBSAPROC_DIZ) $(LIBSAPROC_DEBUGINFO) + $(RM) $(LIBSAPROC_DEBUGINFO) + endif +endif + +install_saproc: $(BUILDLIBSAPROC) + $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ + echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test -f $(LIBSAPROC_DEBUGINFO) && \ + cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ + test -f $(LIBSAPROC_DIZ) && \ + cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \ + cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ + fi + +.PHONY: install_saproc diff --git a/hotspot/make/aix/makefiles/top.make b/hotspot/make/aix/makefiles/top.make new file mode 100644 index 00000000000..95e6e6856e8 --- /dev/null +++ b/hotspot/make/aix/makefiles/top.make @@ -0,0 +1,144 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# top.make is included in the Makefile in the build directories. +# It DOES NOT include the vm dependency info in order to be faster. +# Its main job is to implement the incremental form of make lists. +# It also: +# -builds and runs adlc via adlc.make +# -generates JVMTI source and docs via jvmti.make (JSR-163) +# -generate sa-jdi.jar (JDI binding to core files) + +# It assumes the following flags are set: +# CFLAGS Platform_file, Src_Dirs_I, Src_Dirs_V, SYSDEFS, AOUT, Obj_Files + +# -- D. Ungar (5/97) from a file by Bill Bush + +# Don't override the built-in $(MAKE). +# Instead, use "gmake" (or "gnumake") from the command line. --Rose +#MAKE = gmake + +include $(GAMMADIR)/make/altsrc.make + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +VM = $(GAMMADIR)/src/share/vm +Plat_File = $(Platform_file) +CDG = cd $(GENERATED); + +ifneq ($(USE_PRECOMPILED_HEADER),0) +UpdatePCH = $(MAKE) -f vm.make $(PRECOMPILED_HEADER) $(MFLAGS) +else +UpdatePCH = \# precompiled header is not used +endif + +Cached_plat = $(GENERATED)/platform.current + +AD_Dir = $(GENERATED)/adfiles +ADLC = $(AD_Dir)/adlc +AD_Spec = $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm/$(Platform_arch_model).ad) +AD_Src = $(call altsrc-replace,$(HS_COMMON_SRC)/share/vm/adlc) +AD_Names = ad_$(Platform_arch_model).hpp ad_$(Platform_arch_model).cpp +AD_Files = $(AD_Names:%=$(AD_Dir)/%) + +# AD_Files_If_Required/COMPILER1 = ad_stuff +AD_Files_If_Required/COMPILER2 = ad_stuff +AD_Files_If_Required/TIERED = ad_stuff +AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE)) + +# Wierd argument adjustment for "gnumake -j..." +adjust-mflags = $(GENERATED)/adjust-mflags +MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"` + + +# default target: update lists, make vm +# done in stages to force sequential order with parallel make +# + +default: vm_build_preliminaries the_vm + @echo All done. + +# This is an explicit dependency for the sake of parallel makes. +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) trace_stuff jvmti_stuff sa_stuff + @# We need a null action here, so implicit rules don't get consulted. + +$(Cached_plat): $(Plat_File) + $(CDG) cp $(Plat_File) $(Cached_plat) + +# make AD files as necessary +ad_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f adlc.make $(MFLAGS-adjusted) + +# generate JVMTI files from the spec +jvmti_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f jvmti.make $(MFLAGS-adjusted) + +# generate trace files +trace_stuff: jvmti_stuff $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f trace.make $(MFLAGS-adjusted) + +# generate SA jar files and native header +sa_stuff: + @$(MAKE) -f sa.make $(MFLAGS-adjusted) + +# and the VM: must use other makefile with dependencies included + +# We have to go to great lengths to get control over the -jN argument +# to the recursive invocation of vm.make. The problem is that gnumake +# resets -jN to -j1 for recursive runs. (How helpful.) +# Note that the user must specify the desired parallelism level via a +# command-line or environment variable name HOTSPOT_BUILD_JOBS. +$(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags.sh + @+rm -f $@ $@+ + @+cat $< > $@+ + @+chmod +x $@+ + @+mv $@+ $@ + +the_vm: vm_build_preliminaries $(adjust-mflags) + @$(UpdatePCH) + @$(MAKE) -f vm.make $(MFLAGS-adjusted) + +install gamma: the_vm + @$(MAKE) -f vm.make $@ + +# next rules support "make foo.[ois]" + +%.o %.i %.s: + $(UpdatePCH) + $(MAKE) -f vm.make $(MFLAGS) $@ + #$(MAKE) -f vm.make $@ + +# this should force everything to be rebuilt +clean: + rm -f $(GENERATED)/*.class + $(MAKE) -f vm.make $(MFLAGS) clean + +# just in case it doesn't, this should do it +realclean: + $(MAKE) -f vm.make $(MFLAGS) clean + rm -fr $(GENERATED) + +.PHONY: default vm_build_preliminaries +.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean +.PHONY: checks check_os_version install diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make new file mode 100644 index 00000000000..f173e0ad3ab --- /dev/null +++ b/hotspot/make/aix/makefiles/trace.make @@ -0,0 +1,120 @@ +# +# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 makefile (trace.make) is included from the trace.make in the +# build directories. +# +# It knows how to build and run the tools to generate trace files. + +include $(GAMMADIR)/make/linux/makefiles/rules.make +include $(GAMMADIR)/make/altsrc.make + +# ######################################################################### + +HAS_ALT_SRC:=$(shell if [ -d $(HS_ALT_SRC)/share/vm/trace ]; then \ + echo "true"; else echo "false";\ + fi) + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles +TraceOutDir = $(GENERATED)/tracefiles + +TraceAltSrcDir = $(HS_ALT_SRC)/share/vm/trace +TraceSrcDir = $(HS_COMMON_SRC)/share/vm/trace + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(TraceSrcDir) $(TraceAltSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +TraceGeneratedNames = \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp + +ifeq ($(HAS_ALT_SRC), true) +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp + +ifneq ($(INCLUDE_TRACE), false) +TraceGeneratedNames += traceProducer.cpp +endif + +endif + +TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) + +XSLT = $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ + $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod +ifeq ($(HAS_ALT_SRC), true) + XML_DEPS += $(TraceAltSrcDir)/traceevents.xml +endif + +.PHONY: all clean cleanall + +# ######################################################################### + +all: $(TraceGeneratedFiles) + +GENERATE_CODE= \ + $(QUIETLY) echo Generating $@; \ + $(XSLT) -IN $(word 1,$^) -XSL $(word 2,$^) -OUT $@; \ + test -f $@ + +$(TraceOutDir)/traceEventIds.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventIds.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceTypes.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceTypes.xsl $(XML_DEPS) + $(GENERATE_CODE) + +ifeq ($(HAS_ALT_SRC), false) + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +else + +$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) + $(GENERATE_CODE) + +$(TraceOutDir)/traceEventControl.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventControl.xsl $(XML_DEPS) + $(GENERATE_CODE) + +endif + +# ######################################################################### + +clean cleanall: + rm $(TraceGeneratedFiles) + + diff --git a/hotspot/make/aix/makefiles/vm.make b/hotspot/make/aix/makefiles/vm.make new file mode 100644 index 00000000000..a07b67ec772 --- /dev/null +++ b/hotspot/make/aix/makefiles/vm.make @@ -0,0 +1,377 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, 2013 SAP AG. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Rules to build JVM and related libraries, included from vm.make in the build +# directory. + +# Common build rules. +MAKEFILES_DIR=$(GAMMADIR)/make/$(Platform_os_family)/makefiles +include $(MAKEFILES_DIR)/rules.make +include $(GAMMADIR)/make/altsrc.make + +default: build + +#---------------------------------------------------------------------- +# Defs + +GENERATED = ../generated +DEP_DIR = $(GENERATED)/dependencies + +# reads the generated files defining the set of .o's and the .o .h dependencies +-include $(DEP_DIR)/*.d + +# read machine-specific adjustments (%%% should do this via buildtree.make?) +ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) + include $(MAKEFILES_DIR)/zeroshark.make +else + include $(MAKEFILES_DIR)/$(BUILDARCH).make +endif + +# set VPATH so make knows where to look for source files +# Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm +# The adfiles directory contains ad_.[ch]pp. +# The jvmtifiles directory contains jvmti*.[ch]pp +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles +VPATH += $(Src_Dirs_V:%=%:) + +# set INCLUDES for C preprocessor. +Src_Dirs_I += $(GENERATED) +# The order is important for the precompiled headers to work. +INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%) + +# SYMFLAG is used by {jsig,saproc}.make +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + # always build with debug info when we can create .debuginfo files + SYMFLAG = -g +else + ifeq (${VERSION}, debug) + SYMFLAG = -g + else + SYMFLAG = + endif +endif + +# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined +# in $(GAMMADIR)/make/defs.make +ifeq ($(HOTSPOT_BUILD_VERSION),) + BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)\"" +else + BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)\"" +endif + +# The following variables are defined in the generated flags.make file. +BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HS_BUILD_VER)\"" +JRE_VERSION = -DJRE_RELEASE_VERSION="\"$(JRE_RELEASE_VER)\"" +HS_LIB_ARCH = -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" +BUILD_TARGET = -DHOTSPOT_BUILD_TARGET="\"$(TARGET)\"" +BUILD_USER = -DHOTSPOT_BUILD_USER="\"$(HOTSPOT_BUILD_USER)\"" +VM_DISTRO = -DHOTSPOT_VM_DISTRO="\"$(HOTSPOT_VM_DISTRO)\"" + +CXXFLAGS = \ + ${SYSDEFS} \ + ${INCLUDES} \ + ${BUILD_VERSION} \ + ${BUILD_TARGET} \ + ${BUILD_USER} \ + ${HS_LIB_ARCH} \ + ${VM_DISTRO} + +# This is VERY important! The version define must only be supplied to vm_version.o +# If not, ccache will not re-use the cache at all, since the version string might contain +# a time and date. +vm_version.o: CXXFLAGS += ${JRE_VERSION} + +CXXFLAGS/BYFILE = $(CXXFLAGS/$@) + +# File specific flags +CXXFLAGS += $(CXXFLAGS/BYFILE) + + +# CFLAGS_WARN holds compiler options to suppress/enable warnings. +CFLAGS += $(CFLAGS_WARN/BYFILE) + +# Do not use C++ exception handling +CFLAGS += $(CFLAGS/NOEX) + +# Extra flags from gnumake's invocation or environment +CFLAGS += $(EXTRA_CFLAGS) +LFLAGS += $(EXTRA_CFLAGS) + +# Don't set excutable bit on stack segment +# the same could be done by separate execstack command +#LFLAGS += -Xlinker -z -Xlinker noexecstack + +LIBS += -lm -ldl -lpthread + +# By default, link the *.o into the library, not the executable. +LINK_INTO$(LINK_INTO) = LIBJVM + +JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH) + +#---------------------------------------------------------------------- +# jvm_db & dtrace +include $(MAKEFILES_DIR)/dtrace.make + +#---------------------------------------------------------------------- +# JVM + +JVM = jvm +LIBJVM = lib$(JVM).so + +CFLAGS += -DALLOW_OPERATOR_NEW_USAGE + +LIBJVM_DEBUGINFO = lib$(JVM).debuginfo +LIBJVM_DIZ = lib$(JVM).diz + +SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt + +SOURCE_PATHS=\ + $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \ + \( -name DUMMY $(foreach dir,$(SPECIAL_PATHS),-o -name $(dir)) \)) +SOURCE_PATHS+=$(HS_COMMON_SRC)/os/$(Platform_os_family)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(SRCARCH)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_family)_$(SRCARCH)/vm + +CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) +CORE_PATHS+=$(GENERATED)/jvmtifiles $(GENERATED)/tracefiles + +ifneq ($(INCLUDE_TRACE), false) +CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) +endif + +COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) +COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 + +COMPILER2_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/opto) +COMPILER2_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/libadt) +COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/opto +COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/libadt +COMPILER2_PATHS += $(GENERATED)/adfiles + +SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark + +# Include dirs per type. +Src_Dirs/CORE := $(CORE_PATHS) +Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) +Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) +Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) +Src_Dirs/ZERO := $(CORE_PATHS) +Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS) +Src_Dirs := $(Src_Dirs/$(TYPE)) + +COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\* +COMPILER1_SPECIFIC_FILES := c1_\* +SHARK_SPECIFIC_FILES := shark +ZERO_SPECIFIC_FILES := zero + +# Always exclude these. +Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp + +# Exclude per type. +Src_Files_EXCLUDE/CORE := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) +Src_Files_EXCLUDE/TIERED := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) +Src_Files_EXCLUDE/ZERO := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) + +Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE)) + +# Disable 155427 on aix. +Src_Files_EXCLUDE += decoder_elf.cpp elfFile.cpp elfStringTable.cpp elfSymbolTable.cpp + +# Special handling of arch model. +ifeq ($(Platform_arch_model), x86_32) +Src_Files_EXCLUDE += \*x86_64\* +endif +ifeq ($(Platform_arch_model), x86_64) +Src_Files_EXCLUDE += \*x86_32\* +endif + +# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. +define findsrc + $(notdir $(shell find $(1)/. ! -name . -prune \ + -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \))) +endef + +Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) + +Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files)))) + +JVM_OBJ_FILES = $(Obj_Files) + +vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) + +mapfile : $(MAPFILE) vm.def + rm -f $@ + awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \ + { system ("cat vm.def"); } \ + else \ + { print $$0 } \ + }' > $@ < $(MAPFILE) + +mapfile_reorder : mapfile $(REORDERFILE) + rm -f $@ + cat $^ > $@ + +vm.def: $(Res_Files) $(Obj_Files) + sh $(GAMMADIR)/make/aix/makefiles/build_vm_def.sh *.o > $@ + +ifeq ($(JVM_VARIANT_ZEROSHARK), true) + STATIC_CXX = false +else + ifeq ($(ZERO_LIBARCH), ppc64) + STATIC_CXX = false + else + STATIC_CXX = true + endif +endif + +ifeq ($(LINK_INTO),AOUT) + LIBJVM.o = + LIBJVM_MAPFILE = + LIBS_VM = $(LIBS) +else + LIBJVM.o = $(JVM_OBJ_FILES) + LIBJVM_MAPFILE$(LDNOMAP) = mapfile_reorder + LFLAGS_VM$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LIBJVM_MAPFILE)) +# xlC_r ignores the -o= syntax +# LFLAGS_VM += $(SONAMEFLAG:SONAME=$(LIBJVM)) + + # JVM is statically linked with libgcc[_s] and libstdc++; this is needed to + # get around library dependency and compatibility issues. Must use gcc not + # g++ to link. + LIBS_VM += $(STATIC_STDCXX) $(LIBS) +endif + +LINK_VM = $(LINK_LIB.CXX) + +# create loadmap for libjvm.so by default. Helps in diagnosing some problems. +LFLAGS_VM += -bloadmap:libjvm.loadmap + +# rule for building precompiled header +$(PRECOMPILED_HEADER): + $(QUIETLY) echo Generating precompiled header $@ + $(QUIETLY) mkdir -p $(PRECOMPILED_HEADER_DIR) + $(QUIETLY) $(COMPILE.CXX) $(DEPFLAGS) -x c++-header $(PRECOMPILED_HEADER_SRC) -o $@ $(COMPILE_DONE) + +# making the library: + +ifneq ($(JVM_BASE_ADDR),) +# By default shared library is linked at base address == 0. Modify the +# linker script if JVM prefers a different base location. It can also be +# implemented with 'prelink -r'. But 'prelink' is not (yet) available on +# our build platform (AS-2.1). +LD_SCRIPT = libjvm.so.lds +$(LD_SCRIPT): $(LIBJVM_MAPFILE) + $(QUIETLY) { \ + rm -rf $@; \ + $(LINK_VM) -Wl,--verbose $(LFLAGS_VM) 2>&1 | \ + sed -e '/^======/,/^======/!d' \ + -e '/^======/d' \ + -e 's/0\( + SIZEOF_HEADERS\)/$(JVM_BASE_ADDR)\1/' \ + > $@; \ + } +LD_SCRIPT_FLAG = -Wl,-T,$(LD_SCRIPT) +endif + +# With more recent Redhat releases (or the cutting edge version Fedora), if +# SELinux is configured to be enabled, the runtime linker will fail to apply +# the text relocation to libjvm.so considering that it is built as a non-PIC +# DSO. To workaround that, we run chcon to libjvm.so after it is built. See +# details in bug 6538311. +$(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) + $(QUIETLY) { \ + echo Linking vm...; \ + $(LINK_LIB.CXX/PRE_HOOK) \ + $(LINK_VM) $(LD_SCRIPT_FLAG) \ + $(LFLAGS_VM) -o $@ $(sort $(LIBJVM.o)) $(LIBS_VM); \ + $(LINK_LIB.CXX/POST_HOOK) \ + rm -f $@.1; ln -s $@ $@.1; \ + } +# No security contexts on AIX +# if [ \"$(CROSS_COMPILE_ARCH)\" = \"\" ] ; then \ +# if [ -x /usr/sbin/selinuxenabled ] ; then \ +# /usr/sbin/selinuxenabled; \ +# if [ $$? = 0 ] ; then \ +# /usr/bin/chcon -t textrel_shlib_t $@; \ +# if [ $$? != 0 ]; then \ +# echo "ERROR: Cannot chcon $@"; \ +# fi \ +# fi \ +# fi \ +# fi \ +# } + +#ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) +# $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) +# $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ +# ifeq ($(STRIP_POLICY),all_strip) +# $(QUIETLY) $(STRIP) $@ +# else +# ifeq ($(STRIP_POLICY),min_strip) +# $(QUIETLY) $(STRIP) -g $@ +# # implied else here is no stripping at all +# endif +# endif +# ifeq ($(ZIP_DEBUGINFO_FILES),1) +# $(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) +# $(RM) $(LIBJVM_DEBUGINFO) +# endif +#endif + +DEST_SUBDIR = $(JDK_LIBDIR)/$(VM_SUBDIR) +DEST_JVM = $(DEST_SUBDIR)/$(LIBJVM) +DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO) +DEST_JVM_DIZ = $(DEST_SUBDIR)/$(LIBJVM_DIZ) + +install_jvm: $(LIBJVM) + @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) + $(QUIETLY) test -f $(LIBJVM_DIZ) && \ + cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ) + $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" + +#---------------------------------------------------------------------- +# Other files + +# Signal interposition library +include $(MAKEFILES_DIR)/jsig.make + +# Serviceability agent +include $(MAKEFILES_DIR)/saproc.make + +#---------------------------------------------------------------------- + +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) + +install: install_jvm install_jsig install_saproc + +.PHONY: default build install install_jvm diff --git a/hotspot/make/aix/makefiles/xlc.make b/hotspot/make/aix/makefiles/xlc.make new file mode 100644 index 00000000000..f281a08ea4f --- /dev/null +++ b/hotspot/make/aix/makefiles/xlc.make @@ -0,0 +1,159 @@ +# +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2013 SAP. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +#------------------------------------------------------------------------ +# CC, CXX & AS + +# Set compiler explicitly +CXX = $(COMPILER_PATH)xlC_r +CC = $(COMPILER_PATH)xlc_r +HOSTCXX = $(CXX) +HOSTCC = $(CC) + +AS = $(CC) -c + +# get xlc version +CXX_VERSION := $(shell $(CXX) -qversion 2>&1 | sed -n 's/.*Version: \([0-9.]*\)/\1/p') + +# xlc 08.00.0000.0023 and higher supports -qtune=balanced +CXX_SUPPORTS_BALANCED_TUNING=$(shell if [ $(subst .,,$(CXX_VERSION)) -ge 080000000023 ] ; then echo "true" ; fi) +# xlc 10.01 is used with aggressive optimizations to boost performance +CXX_IS_V10=$(shell if [ $(subst .,,$(CXX_VERSION)) -ge 100100000000 ] ; then echo "true" ; fi) + +# check for precompiled headers support + +# Switch off the precompiled header support. Neither xlC 8.0 nor xlC 10.0 +# support precompiled headers. Both "understand" the command line switches "-qusepcomp" and +# "-qgenpcomp" but when we specify them the following message is printed: +# "1506-755 (W) The -qusepcomp option is not supported in this release." +USE_PRECOMPILED_HEADER = 0 +ifneq ($(USE_PRECOMPILED_HEADER),0) +PRECOMPILED_HEADER_DIR=. +PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled/precompiled.hpp +PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch +endif + + +#------------------------------------------------------------------------ +# Compiler flags + +# position-independent code +PICFLAG = -qpic=large + +VM_PICFLAG/LIBJVM = $(PICFLAG) +VM_PICFLAG/AOUT = +VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO)) + +CFLAGS += $(VM_PICFLAG) +CFLAGS += -qnortti +CFLAGS += -qnoeh + +CFLAGS += -D_REENTRANT +# no xlc counterpart for -fcheck-new +# CFLAGS += -fcheck-new + +ARCHFLAG = -q64 + +CFLAGS += $(ARCHFLAG) +AOUT_FLAGS += $(ARCHFLAG) +LFLAGS += $(ARCHFLAG) +ASFLAGS += $(ARCHFLAG) + +# Use C++ Interpreter +ifdef CC_INTERP + CFLAGS += -DCC_INTERP +endif + +# Keep temporary files (.ii, .s) +# no counterpart on xlc for -save-temps, -pipe + +# Compiler warnings are treated as errors +# Do not treat warnings as errors +# WARNINGS_ARE_ERRORS = -Werror +# Except for a few acceptable ones +# ACCEPTABLE_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare +# CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ACCEPTABLE_WARNINGS) +CFLAGS_WARN/COMMON = +CFLAGS_WARN/DEFAULT = $(CFLAGS_WARN/COMMON) $(EXTRA_WARNINGS) +# Special cases +CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) + +# The flags to use for an optimized build +OPT_CFLAGS += -O3 + +# Hotspot uses very unstrict aliasing turn this optimization off +OPT_CFLAGS += -qalias=noansi + +OPT_CFLAGS/NOOPT=-qnoopt + +DEPFLAGS = -qmakedep=gcc -MF $(DEP_DIR)/$(@:%=%.d) + +#------------------------------------------------------------------------ +# Linker flags + +# statically link libstdc++.so, work with gcc but ignored by g++ +STATIC_STDCXX = -Wl,-lC_r + +# Enable linker optimization +# no counterpart on xlc for this +# LFLAGS += -Xlinker -O1 + +# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file. +# MAPFLAG = -Xlinker --version-script=FILENAME + +# Build shared library +SHARED_FLAG = -q64 -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath + +#------------------------------------------------------------------------ +# Debug flags + +# Always compile with '-g' to get symbols in the stacktraces in the hs_err file +DEBUG_CFLAGS += -g +FASTDEBUG_CFLAGS += -g +OPT_CFLAGS += -g + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + DEBUG_CFLAGS = -g + CFLAGS += $(DEBUG_CFLAGS) +endif + +# If we are building HEADLESS, pass on to VM +# so it can set the java.awt.headless property +ifdef HEADLESS +CFLAGS += -DHEADLESS +endif + +# We are building Embedded for a small device +# favor code space over speed +ifdef MINIMIZE_RAM_USAGE +CFLAGS += -DMINIMIZE_RAM_USAGE +endif + +ifdef CROSS_COMPILE_ARCH + STRIP = $(ALT_COMPILER_PATH)/strip +else + STRIP = strip +endif diff --git a/hotspot/make/aix/platform_ppc64 b/hotspot/make/aix/platform_ppc64 new file mode 100644 index 00000000000..5a21fb9c031 --- /dev/null +++ b/hotspot/make/aix/platform_ppc64 @@ -0,0 +1,17 @@ +os_family = aix + +arch = ppc + +arch_model = ppc_64 + +os_arch = aix_ppc + +os_arch_model = aix_ppc_64 + +lib_arch = ppc64 + +compiler = xlc + +gnu_dis_arch = ppc64 + +sysdefs = -DAIX -DPPC64 diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index 07a191e479b..01479a92fac 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -166,11 +166,15 @@ ifeq ($(OS),) HOST := $(shell uname -n) endif -# If not SunOS, not Linux and not BSD, assume Windows +# If not SunOS, not Linux not BSD and not AIX, assume Windows ifneq ($(OS), Linux) ifneq ($(OS), SunOS) ifneq ($(OS), bsd) - OSNAME=windows + ifneq ($(OS), AIX) + OSNAME=windows + else + OSNAME=aix + endif else OSNAME=bsd endif From 2af861eed12bf1783da5937b5375dd1364f6c001 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Fri, 6 Sep 2013 20:16:09 +0200 Subject: [PATCH 019/265] 8023038: PPC64 (part 15): Platform files for AIX/PPC64 support Reviewed-by: kvn --- hotspot/src/os/aix/vm/attachListener_aix.cpp | 574 ++ hotspot/src/os/aix/vm/c2_globals_aix.hpp | 37 + hotspot/src/os/aix/vm/decoder_aix.hpp | 48 + hotspot/src/os/aix/vm/globals_aix.hpp | 63 + .../src/os/aix/vm/interfaceSupport_aix.hpp | 35 + hotspot/src/os/aix/vm/jsig.c | 233 + hotspot/src/os/aix/vm/jvm_aix.cpp | 201 + hotspot/src/os/aix/vm/jvm_aix.h | 123 + hotspot/src/os/aix/vm/libperfstat_aix.cpp | 124 + hotspot/src/os/aix/vm/libperfstat_aix.hpp | 59 + hotspot/src/os/aix/vm/loadlib_aix.cpp | 185 + hotspot/src/os/aix/vm/loadlib_aix.hpp | 128 + hotspot/src/os/aix/vm/mutex_aix.inline.hpp | 33 + hotspot/src/os/aix/vm/osThread_aix.cpp | 58 + hotspot/src/os/aix/vm/osThread_aix.hpp | 144 + hotspot/src/os/aix/vm/os_aix.cpp | 5126 +++++++++++++++++ hotspot/src/os/aix/vm/os_aix.hpp | 385 ++ hotspot/src/os/aix/vm/os_aix.inline.hpp | 286 + hotspot/src/os/aix/vm/os_share_aix.hpp | 37 + hotspot/src/os/aix/vm/perfMemory_aix.cpp | 1026 ++++ hotspot/src/os/aix/vm/porting_aix.cpp | 367 ++ hotspot/src/os/aix/vm/porting_aix.hpp | 81 + hotspot/src/os/aix/vm/threadCritical_aix.cpp | 68 + hotspot/src/os/aix/vm/thread_aix.inline.hpp | 42 + hotspot/src/os/aix/vm/vmError_aix.cpp | 122 + .../aix_ppc/vm/atomic_aix_ppc.inline.hpp | 401 ++ .../src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp | 54 + .../aix_ppc/vm/orderAccess_aix_ppc.inline.hpp | 147 + hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp | 560 ++ hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp | 35 + .../aix_ppc/vm/prefetch_aix_ppc.inline.hpp | 58 + .../os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp | 40 + .../os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp | 36 + .../src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp | 36 + .../src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp | 79 + .../os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp | 55 + .../vm/utilities/globalDefinitions_xlc.hpp | 202 + 37 files changed, 11288 insertions(+) create mode 100644 hotspot/src/os/aix/vm/attachListener_aix.cpp create mode 100644 hotspot/src/os/aix/vm/c2_globals_aix.hpp create mode 100644 hotspot/src/os/aix/vm/decoder_aix.hpp create mode 100644 hotspot/src/os/aix/vm/globals_aix.hpp create mode 100644 hotspot/src/os/aix/vm/interfaceSupport_aix.hpp create mode 100644 hotspot/src/os/aix/vm/jsig.c create mode 100644 hotspot/src/os/aix/vm/jvm_aix.cpp create mode 100644 hotspot/src/os/aix/vm/jvm_aix.h create mode 100644 hotspot/src/os/aix/vm/libperfstat_aix.cpp create mode 100644 hotspot/src/os/aix/vm/libperfstat_aix.hpp create mode 100644 hotspot/src/os/aix/vm/loadlib_aix.cpp create mode 100644 hotspot/src/os/aix/vm/loadlib_aix.hpp create mode 100644 hotspot/src/os/aix/vm/mutex_aix.inline.hpp create mode 100644 hotspot/src/os/aix/vm/osThread_aix.cpp create mode 100644 hotspot/src/os/aix/vm/osThread_aix.hpp create mode 100644 hotspot/src/os/aix/vm/os_aix.cpp create mode 100644 hotspot/src/os/aix/vm/os_aix.hpp create mode 100644 hotspot/src/os/aix/vm/os_aix.inline.hpp create mode 100644 hotspot/src/os/aix/vm/os_share_aix.hpp create mode 100644 hotspot/src/os/aix/vm/perfMemory_aix.cpp create mode 100644 hotspot/src/os/aix/vm/porting_aix.cpp create mode 100644 hotspot/src/os/aix/vm/porting_aix.hpp create mode 100644 hotspot/src/os/aix/vm/threadCritical_aix.cpp create mode 100644 hotspot/src/os/aix/vm/thread_aix.inline.hpp create mode 100644 hotspot/src/os/aix/vm/vmError_aix.cpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp create mode 100644 hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp create mode 100644 hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp diff --git a/hotspot/src/os/aix/vm/attachListener_aix.cpp b/hotspot/src/os/aix/vm/attachListener_aix.cpp new file mode 100644 index 00000000000..5b7cb29f115 --- /dev/null +++ b/hotspot/src/os/aix/vm/attachListener_aix.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/os.hpp" +#include "services/attachListener.hpp" +#include "services/dtraceAttacher.hpp" + +#include +#include +#include +#include +#include +#include + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path) +#endif + +// The attach mechanism on Linux uses a UNIX domain socket. An attach listener +// thread is created at startup or is created on-demand via a signal from +// the client tool. The attach listener creates a socket and binds it to a file +// in the filesystem. The attach listener then acts as a simple (single- +// threaded) server - it waits for a client to connect, reads the request, +// executes it, and returns the response to the client via the socket +// connection. +// +// As the socket is a UNIX domain socket it means that only clients on the +// local machine can connect. In addition there are two other aspects to +// the security: +// 1. The well known file that the socket is bound to has permission 400 +// 2. When a client connect, the SO_PEERID socket option is used to +// obtain the credentials of client. We check that the effective uid +// of the client matches this process. + +// forward reference +class AixAttachOperation; + +class AixAttachListener: AllStatic { + private: + // the path to which we bind the UNIX domain socket + static char _path[UNIX_PATH_MAX]; + static bool _has_path; + // Shutdown marker to prevent accept blocking during clean-up. + static bool _shutdown; + + // the file descriptor for the listening socket + static int _listener; + + static void set_path(char* path) { + if (path == NULL) { + _has_path = false; + } else { + strncpy(_path, path, UNIX_PATH_MAX); + _path[UNIX_PATH_MAX-1] = '\0'; + _has_path = true; + } + } + + static void set_listener(int s) { _listener = s; } + + // reads a request from the given connected socket + static AixAttachOperation* read_request(int s); + + public: + enum { + ATTACH_PROTOCOL_VER = 1 // protocol version + }; + enum { + ATTACH_ERROR_BADVERSION = 101 // error codes + }; + + // initialize the listener, returns 0 if okay + static int init(); + + static char* path() { return _path; } + static bool has_path() { return _has_path; } + static int listener() { return _listener; } + // Shutdown marker to prevent accept blocking during clean-up + static void set_shutdown(bool shutdown) { _shutdown = shutdown; } + static bool is_shutdown() { return _shutdown; } + + // write the given buffer to a socket + static int write_fully(int s, char* buf, int len); + + static AixAttachOperation* dequeue(); +}; + +class AixAttachOperation: public AttachOperation { + private: + // the connection to the client + int _socket; + + public: + void complete(jint res, bufferedStream* st); + + void set_socket(int s) { _socket = s; } + int socket() const { return _socket; } + + AixAttachOperation(char* name) : AttachOperation(name) { + set_socket(-1); + } +}; + +// statics +char AixAttachListener::_path[UNIX_PATH_MAX]; +bool AixAttachListener::_has_path; +int AixAttachListener::_listener = -1; +// Shutdown marker to prevent accept blocking during clean-up +bool AixAttachListener::_shutdown = false; + +// Supporting class to help split a buffer into individual components +class ArgumentIterator : public StackObj { + private: + char* _pos; + char* _end; + public: + ArgumentIterator(char* arg_buffer, size_t arg_size) { + _pos = arg_buffer; + _end = _pos + arg_size - 1; + } + char* next() { + if (*_pos == '\0') { + return NULL; + } + char* res = _pos; + char* next_pos = strchr(_pos, '\0'); + if (next_pos < _end) { + next_pos++; + } + _pos = next_pos; + return res; + } +}; + +// On AIX if sockets block until all data has been transmitted +// successfully in some communication domains a socket "close" may +// never complete. We have to take care that after the socket shutdown +// the listener never enters accept state. + +// atexit hook to stop listener and unlink the file that it is +// bound too. + +// Some modifications to the listener logic to prevent deadlocks on exit. +// 1. We Shutdown the socket here instead. AixAttachOperation::complete() is not the right place +// since more than one agent in a sequence in JPLIS live tests wouldn't work (Listener thread +// would be dead after the first operation completion). +// 2. close(s) may never return if the listener thread is in socket accept(). Unlinking the file +// should be sufficient for cleanup. +extern "C" { + static void listener_cleanup() { + static int cleanup_done; + if (!cleanup_done) { + cleanup_done = 1; + AixAttachListener::set_shutdown(true); + int s = AixAttachListener::listener(); + if (s != -1) { + ::shutdown(s, 2); + } + if (AixAttachListener::has_path()) { + ::unlink(AixAttachListener::path()); + } + } + } +} + +// Initialization - create a listener socket and bind it to a file + +int AixAttachListener::init() { + char path[UNIX_PATH_MAX]; // socket file + char initial_path[UNIX_PATH_MAX]; // socket file during setup + int listener; // listener socket (file descriptor) + + // register function to cleanup + ::atexit(listener_cleanup); + + int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", + os::get_temp_directory(), os::current_process_id()); + if (n < (int)UNIX_PATH_MAX) { + n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); + } + if (n >= (int)UNIX_PATH_MAX) { + return -1; + } + + // create the listener socket + listener = ::socket(PF_UNIX, SOCK_STREAM, 0); + if (listener == -1) { + return -1; + } + + // bind socket + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, initial_path); + ::unlink(initial_path); + // We must call bind with the actual socketaddr length. This is obligatory for AS400. + int res = ::bind(listener, (struct sockaddr*)&addr, SUN_LEN(&addr)); + if (res == -1) { + RESTARTABLE(::close(listener), res); + return -1; + } + + // put in listen mode, set permissions, and rename into place + res = ::listen(listener, 5); + if (res == 0) { + RESTARTABLE(::chmod(initial_path, (S_IREAD|S_IWRITE) & ~(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)), res); + if (res == 0) { + res = ::rename(initial_path, path); + } + } + if (res == -1) { + RESTARTABLE(::close(listener), res); + ::unlink(initial_path); + return -1; + } + set_path(path); + set_listener(listener); + set_shutdown(false); + + return 0; +} + +// Given a socket that is connected to a peer we read the request and +// create an AttachOperation. As the socket is blocking there is potential +// for a denial-of-service if the peer does not response. However this happens +// after the peer credentials have been checked and in the worst case it just +// means that the attach listener thread is blocked. +// +AixAttachOperation* AixAttachListener::read_request(int s) { + char ver_str[8]; + sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); + + // The request is a sequence of strings so we first figure out the + // expected count and the maximum possible length of the request. + // The request is: + // 00000 + // where is the protocol version (1), is the command + // name ("load", "datadump", ...), and is an argument + int expected_str_count = 2 + AttachOperation::arg_count_max; + const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) + + AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1); + + char buf[max_len]; + int str_count = 0; + + // Read until all (expected) strings have been read, the buffer is + // full, or EOF. + + int off = 0; + int left = max_len; + + do { + int n; + // Don't block on interrupts because this will + // hang in the clean-up when shutting down. + n = read(s, buf+off, left); + if (n == -1) { + return NULL; // reset by peer or other error + } + if (n == 0) { // end of file reached + break; + } + for (int i=0; i so check it now to + // check for protocol mis-match + if (str_count == 1) { + if ((strlen(buf) != strlen(ver_str)) || + (atoi(buf) != ATTACH_PROTOCOL_VER)) { + char msg[32]; + sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); + write_fully(s, msg, strlen(msg)); + return NULL; + } + } + } + } + off += n; + left -= n; + } while (left > 0 && str_count < expected_str_count); + + if (str_count != expected_str_count) { + return NULL; // incomplete request + } + + // parse request + + ArgumentIterator args(buf, (max_len)-left); + + // version already checked + char* v = args.next(); + + char* name = args.next(); + if (name == NULL || strlen(name) > AttachOperation::name_length_max) { + return NULL; + } + + AixAttachOperation* op = new AixAttachOperation(name); + + for (int i=0; iset_arg(i, NULL); + } else { + if (strlen(arg) > AttachOperation::arg_length_max) { + delete op; + return NULL; + } + op->set_arg(i, arg); + } + } + + op->set_socket(s); + return op; +} + + +// Dequeue an operation +// +// In the Linux implementation there is only a single operation and clients +// cannot queue commands (except at the socket level). +// +AixAttachOperation* AixAttachListener::dequeue() { + for (;;) { + int s; + + // wait for client to connect + struct sockaddr addr; + socklen_t len = sizeof(addr); + memset(&addr, 0, len); + // We must prevent accept blocking on the socket if it has been shut down. + // Therefore we allow interrups and check whether we have been shut down already. + if (AixAttachListener::is_shutdown()) { + return NULL; + } + s=::accept(listener(), &addr, &len); + if (s == -1) { + return NULL; // log a warning? + } + + // Added timeouts for read and write. If we get no request within the + // next AttachListenerTimeout milliseconds we just finish the connection. + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = AttachListenerTimeout * 1000; + ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)); + ::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); + + // get the credentials of the peer and check the effective uid/guid + // - check with jeff on this. + struct peercred_struct cred_info; + socklen_t optlen = sizeof(cred_info); + if (::getsockopt(s, SOL_SOCKET, SO_PEERID, (void*)&cred_info, &optlen) == -1) { + int res; + RESTARTABLE(::close(s), res); + continue; + } + uid_t euid = geteuid(); + gid_t egid = getegid(); + + if (cred_info.euid != euid || cred_info.egid != egid) { + int res; + RESTARTABLE(::close(s), res); + continue; + } + + // peer credential look okay so we read the request + AixAttachOperation* op = read_request(s); + if (op == NULL) { + int res; + RESTARTABLE(::close(s), res); + continue; + } else { + return op; + } + } +} + +// write the given buffer to the socket +int AixAttachListener::write_fully(int s, char* buf, int len) { + do { + int n = ::write(s, buf, len); + if (n == -1) { + if (errno != EINTR) return -1; + } else { + buf += n; + len -= n; + } + } + while (len > 0); + return 0; +} + +// Complete an operation by sending the operation result and any result +// output to the client. At this time the socket is in blocking mode so +// potentially we can block if there is a lot of data and the client is +// non-responsive. For most operations this is a non-issue because the +// default send buffer is sufficient to buffer everything. In the future +// if there are operations that involves a very big reply then it the +// socket could be made non-blocking and a timeout could be used. + +void AixAttachOperation::complete(jint result, bufferedStream* st) { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + // write operation result + char msg[32]; + sprintf(msg, "%d\n", result); + int rc = AixAttachListener::write_fully(this->socket(), msg, strlen(msg)); + + // write any result data + if (rc == 0) { + // Shutdown the socket in the cleanup function to enable more than + // one agent attach in a sequence (see comments to listener_cleanup()). + AixAttachListener::write_fully(this->socket(), (char*) st->base(), st->size()); + } + + // done + RESTARTABLE(::close(this->socket()), rc); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + delete this; +} + + +// AttachListener functions + +AttachOperation* AttachListener::dequeue() { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + AttachOperation* op = AixAttachListener::dequeue(); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + return op; +} + +// Performs initialization at vm startup +// For AIX we remove any stale .java_pid file which could cause +// an attaching process to think we are ready to receive on the +// domain socket before we are properly initialized + +void AttachListener::vm_start() { + char fn[UNIX_PATH_MAX]; + struct stat64 st; + int ret; + + int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d", + os::get_temp_directory(), os::current_process_id()); + assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow"); + + RESTARTABLE(::stat64(fn, &st), ret); + if (ret == 0) { + ret = ::unlink(fn); + if (ret == -1) { + debug_only(warning("failed to remove stale attach pid file at %s", fn)); + } + } +} + +int AttachListener::pd_init() { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + int ret_code = AixAttachListener::init(); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + return ret_code; +} + +// Attach Listener is started lazily except in the case when +// +ReduseSignalUsage is used +bool AttachListener::init_at_startup() { + if (ReduceSignalUsage) { + return true; + } else { + return false; + } +} + +// If the file .attach_pid exists in the working directory +// or /tmp then this is the trigger to start the attach mechanism +bool AttachListener::is_init_trigger() { + if (init_at_startup() || is_initialized()) { + return false; // initialized at startup or already initialized + } + char fn[PATH_MAX+1]; + sprintf(fn, ".attach_pid%d", os::current_process_id()); + int ret; + struct stat64 st; + RESTARTABLE(::stat64(fn, &st), ret); + if (ret == -1) { + snprintf(fn, sizeof(fn), "%s/.attach_pid%d", + os::get_temp_directory(), os::current_process_id()); + RESTARTABLE(::stat64(fn, &st), ret); + } + if (ret == 0) { + // simple check to avoid starting the attach mechanism when + // a bogus user creates the file + if (st.st_uid == geteuid()) { + init(); + return true; + } + } + return false; +} + +// if VM aborts then remove listener +void AttachListener::abort() { + listener_cleanup(); +} + +void AttachListener::pd_data_dump() { + os::signal_notify(SIGQUIT); +} + +AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { + return NULL; +} + +jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { + out->print_cr("flag '%s' cannot be changed", op->arg(0)); + return JNI_ERR; +} + +void AttachListener::pd_detachall() { + // Cleanup server socket to detach clients. + listener_cleanup(); +} diff --git a/hotspot/src/os/aix/vm/c2_globals_aix.hpp b/hotspot/src/os/aix/vm/c2_globals_aix.hpp new file mode 100644 index 00000000000..ea63015a513 --- /dev/null +++ b/hotspot/src/os/aix/vm/c2_globals_aix.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_C2_GLOBALS_AIX_HPP +#define OS_AIX_VM_C2_GLOBALS_AIX_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// +// Sets the default values for operating system dependent flags used by the +// server compiler. (see c2_globals.hpp) +// + +#endif // OS_AIX_VM_C2_GLOBALS_AIX_HPP diff --git a/hotspot/src/os/aix/vm/decoder_aix.hpp b/hotspot/src/os/aix/vm/decoder_aix.hpp new file mode 100644 index 00000000000..ac234c1ab00 --- /dev/null +++ b/hotspot/src/os/aix/vm/decoder_aix.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "utilities/decoder.hpp" +#include "porting_aix.hpp" + +// Provide simple AIXDecoder which enables decoding of C frames in VM. +class AIXDecoder: public AbstractDecoder { + public: + AIXDecoder() { + _decoder_status = no_error; + } + ~AIXDecoder() {} + + virtual bool can_decode_C_frame_in_vm() const { return true; } + + virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName + + virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) { + return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0) == 0); + } + virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) { + ShouldNotReachHere(); + return false; + } +}; diff --git a/hotspot/src/os/aix/vm/globals_aix.hpp b/hotspot/src/os/aix/vm/globals_aix.hpp new file mode 100644 index 00000000000..dc20a6aa95b --- /dev/null +++ b/hotspot/src/os/aix/vm/globals_aix.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_GLOBALS_AIX_HPP +#define OS_AIX_VM_GLOBALS_AIX_HPP + +// +// Defines Aix specific flags. They are not available on other platforms. +// +#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ + \ + /* If UseLargePages == true allow or deny usage of 16M pages. 16M pages are */ \ + /* a scarce resource and there may be situations where we do not want the VM */ \ + /* to run with 16M pages. (Will fall back to 64K pages). */ \ + product_pd(bool, Use16MPages, \ + "Use 16M pages if available.") \ + \ + /* use optimized addresses for the polling page, */ \ + /* e.g. map it to a special 32-bit address. */ \ + product_pd(bool, OptimizePollingPageLocation, \ + "Optimize the location of the polling page used for Safepoints") \ + \ + product_pd(intx, AttachListenerTimeout, \ + "Timeout in ms the attach listener waits for a request") \ + \ + +// Per default, do not allow 16M pages. 16M pages have to be switched on specifically. +define_pd_global(bool, Use16MPages, false); +define_pd_global(bool, OptimizePollingPageLocation, true); +define_pd_global(intx, AttachListenerTimeout, 1000); + +// +// Defines Aix-specific default values. The flags are available on all +// platforms, but they may have different default values on other platforms. +// +define_pd_global(bool, UseLargePages, true); +define_pd_global(bool, UseLargePagesIndividualAllocation, false); +define_pd_global(bool, UseOSErrorReporting, false); +define_pd_global(bool, UseThreadPriorities, true) ; + +#endif // OS_AIX_VM_GLOBALS_AIX_HPP diff --git a/hotspot/src/os/aix/vm/interfaceSupport_aix.hpp b/hotspot/src/os/aix/vm/interfaceSupport_aix.hpp new file mode 100644 index 00000000000..62e75c7eb72 --- /dev/null +++ b/hotspot/src/os/aix/vm/interfaceSupport_aix.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP +#define OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP + +// Contains inlined functions for class InterfaceSupport + +static inline void serialize_memory(JavaThread *thread) { + os::write_memory_serialize_page(thread); +} + +#endif // OS_LINUX_VM_INTERFACESUPPORT_LINUX_HPP diff --git a/hotspot/src/os/aix/vm/jsig.c b/hotspot/src/os/aix/vm/jsig.c new file mode 100644 index 00000000000..ca15dc595ac --- /dev/null +++ b/hotspot/src/os/aix/vm/jsig.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* CopyrightVersion 1.2 */ + +/* This is a special library that should be loaded before libc & + * libthread to interpose the signal handler installation functions: + * sigaction(), signal(), sigset(). + * Used for signal-chaining. See RFE 4381843. + */ + +#include +#include +#include +#include +#include + +#define bool int +#define true 1 +#define false 0 + +// Highest so far on AIX 5.2 is SIGSAK (63) +#define MAXSIGNUM 63 +#define MASK(sig) ((unsigned int)1 << sig) + +static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ +static unsigned int jvmsigs = 0; /* signals used by jvm */ + +/* used to synchronize the installation of signal handlers */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_t tid = 0; + +typedef void (*sa_handler_t)(int); +typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +// signal_t is already defined on AIX +typedef sa_handler_t (*signal_like_function_t)(int, sa_handler_t); +typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); + +static signal_like_function_t os_signal = 0; /* os's version of signal()/sigset() */ +static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ + +static bool jvm_signal_installing = false; +static bool jvm_signal_installed = false; + +static void signal_lock() { + pthread_mutex_lock(&mutex); + /* When the jvm is installing its set of signal handlers, threads + * other than the jvm thread should wait */ + if (jvm_signal_installing) { + if (tid != pthread_self()) { + pthread_cond_wait(&cond, &mutex); + } + } +} + +static void signal_unlock() { + pthread_mutex_unlock(&mutex); +} + +static sa_handler_t call_os_signal(int sig, sa_handler_t disp, + bool is_sigset) { + if (os_signal == NULL) { + if (!is_sigset) { + // Aix: call functions directly instead of dlsym'ing them + os_signal = signal; + } else { + // Aix: call functions directly instead of dlsym'ing them + os_signal = sigset; + } + if (os_signal == NULL) { + printf("%s\n", dlerror()); + exit(0); + } + } + return (*os_signal)(sig, disp); +} + +static void save_signal_handler(int sig, sa_handler_t disp) { + sigset_t set; + sact[sig].sa_handler = disp; + sigemptyset(&set); + sact[sig].sa_mask = set; + sact[sig].sa_flags = 0; +} + +static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t oldhandler; + bool sigused; + + signal_lock(); + + sigused = (MASK(sig) & jvmsigs) != 0; + if (jvm_signal_installed && sigused) { + /* jvm has installed its signal handler for this signal. */ + /* Save the handler. Don't really install it. */ + oldhandler = sact[sig].sa_handler; + save_signal_handler(sig, disp); + + signal_unlock(); + return oldhandler; + } else if (jvm_signal_installing) { + /* jvm is installing its signal handlers. Install the new + * handlers and save the old ones. jvm uses sigaction(). + * Leave the piece here just in case. */ + oldhandler = call_os_signal(sig, disp, is_sigset); + save_signal_handler(sig, oldhandler); + + /* Record the signals used by jvm */ + jvmsigs |= MASK(sig); + + signal_unlock(); + return oldhandler; + } else { + /* jvm has no relation with this signal (yet). Install the + * the handler. */ + oldhandler = call_os_signal(sig, disp, is_sigset); + + signal_unlock(); + return oldhandler; + } +} + +sa_handler_t signal(int sig, sa_handler_t disp) { + return set_signal(sig, disp, false); +} + +sa_handler_t sigset(int sig, sa_handler_t disp) { + return set_signal(sig, disp, true); + } + +static int call_os_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) { + if (os_sigaction == NULL) { + // Aix: call functions directly instead of dlsym'ing them + os_sigaction = sigaction; + if (os_sigaction == NULL) { + printf("%s\n", dlerror()); + exit(0); + } + } + return (*os_sigaction)(sig, act, oact); +} + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { + int res; + bool sigused; + struct sigaction oldAct; + + signal_lock(); + + sigused = (MASK(sig) & jvmsigs) != 0; + if (jvm_signal_installed && sigused) { + /* jvm has installed its signal handler for this signal. */ + /* Save the handler. Don't really install it. */ + if (oact != NULL) { + *oact = sact[sig]; + } + if (act != NULL) { + sact[sig] = *act; + } + + signal_unlock(); + return 0; + } else if (jvm_signal_installing) { + /* jvm is installing its signal handlers. Install the new + * handlers and save the old ones. */ + res = call_os_sigaction(sig, act, &oldAct); + sact[sig] = oldAct; + if (oact != NULL) { + *oact = oldAct; + } + + /* Record the signals used by jvm */ + jvmsigs |= MASK(sig); + + signal_unlock(); + return res; + } else { + /* jvm has no relation with this signal (yet). Install the + * the handler. */ + res = call_os_sigaction(sig, act, oact); + + signal_unlock(); + return res; + } +} + +/* The three functions for the jvm to call into */ +void JVM_begin_signal_setting() { + signal_lock(); + jvm_signal_installing = true; + tid = pthread_self(); + signal_unlock(); +} + +void JVM_end_signal_setting() { + signal_lock(); + jvm_signal_installed = true; + jvm_signal_installing = false; + pthread_cond_broadcast(&cond); + signal_unlock(); +} + +struct sigaction *JVM_get_signal_action(int sig) { + /* Does race condition make sense here? */ + if ((MASK(sig) & jvmsigs) != 0) { + return &sact[sig]; + } + return NULL; +} diff --git a/hotspot/src/os/aix/vm/jvm_aix.cpp b/hotspot/src/os/aix/vm/jvm_aix.cpp new file mode 100644 index 00000000000..da41a6d6bab --- /dev/null +++ b/hotspot/src/os/aix/vm/jvm_aix.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "prims/jvm.h" +#include "runtime/interfaceSupport.hpp" +#include "runtime/osThread.hpp" + +#include + + +// sun.misc.Signal /////////////////////////////////////////////////////////// +// Signal code is mostly copied from classic vm, signals_md.c 1.4 98/08/23 +/* + * This function is included primarily as a debugging aid. If Java is + * running in a console window, then pressing will cause + * the current state of all active threads and monitors to be written + * to the console window. + */ + +JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) + // Copied from classic vm + // signals_md.c 1.4 98/08/23 + void* newHandler = handler == (void *)2 + ? os::user_handler() + : handler; + switch (sig) { + /* The following are already used by the VM. */ + case INTERRUPT_SIGNAL: + case SIGFPE: + case SIGILL: + case SIGSEGV: + + /* The following signal is used by the VM to dump thread stacks unless + ReduceSignalUsage is set, in which case the user is allowed to set + his own _native_ handler for this signal; thus, in either case, + we do not allow JVM_RegisterSignal to change the handler. */ + case BREAK_SIGNAL: + return (void *)-1; + + /* The following signals are used for Shutdown Hooks support. However, if + ReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked via + System.exit(), Java is not allowed to use these signals, and the the + user is allowed to set his own _native_ handler for these signals and + invoke System.exit() as needed. Terminator.setup() is avoiding + registration of these signals when -Xrs is present. + - If the HUP signal is ignored (from the nohup) command, then Java + is not allowed to use this signal. + */ + + case SHUTDOWN1_SIGNAL: + case SHUTDOWN2_SIGNAL: + case SHUTDOWN3_SIGNAL: + if (ReduceSignalUsage) return (void*)-1; + if (os::Aix::is_sig_ignored(sig)) return (void*)1; + } + + void* oldHandler = os::signal(sig, newHandler); + if (oldHandler == os::user_handler()) { + return (void *)2; + } else { + return oldHandler; + } +JVM_END + + +JVM_ENTRY_NO_ENV(jboolean, JVM_RaiseSignal(jint sig)) + if (ReduceSignalUsage) { + // do not allow SHUTDOWN1_SIGNAL,SHUTDOWN2_SIGNAL,SHUTDOWN3_SIGNAL, + // BREAK_SIGNAL to be raised when ReduceSignalUsage is set, since + // no handler for them is actually registered in JVM or via + // JVM_RegisterSignal. + if (sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL || + sig == SHUTDOWN3_SIGNAL || sig == BREAK_SIGNAL) { + return JNI_FALSE; + } + } + else if ((sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL || + sig == SHUTDOWN3_SIGNAL) && os::Aix::is_sig_ignored(sig)) { + // do not allow SHUTDOWN1_SIGNAL to be raised when SHUTDOWN1_SIGNAL + // is ignored, since no handler for them is actually registered in JVM + // or via JVM_RegisterSignal. + // This also applies for SHUTDOWN2_SIGNAL and SHUTDOWN3_SIGNAL + return JNI_FALSE; + } + + os::signal_raise(sig); + return JNI_TRUE; +JVM_END + +/* + All the defined signal names for Linux. + + NOTE that not all of these names are accepted by our Java implementation + + Via an existing claim by the VM, sigaction restrictions, or + the "rules of Unix" some of these names will be rejected at runtime. + For example the VM sets up to handle USR1, sigaction returns EINVAL for + STOP, and Linux simply doesn't allow catching of KILL. + + Here are the names currently accepted by a user of sun.misc.Signal with + 1.4.1 (ignoring potential interaction with use of chaining, etc): + + HUP, INT, TRAP, ABRT, IOT, BUS, USR2, PIPE, ALRM, TERM, STKFLT, + CLD, CHLD, CONT, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF, + WINCH, POLL, IO, PWR, SYS + +*/ + +struct siglabel { + const char *name; + int number; +}; + +struct siglabel siglabels[] = { + /* derived from /usr/include/bits/signum.h on RH7.2 */ + "HUP", SIGHUP, /* Hangup (POSIX). */ + "INT", SIGINT, /* Interrupt (ANSI). */ + "QUIT", SIGQUIT, /* Quit (POSIX). */ + "ILL", SIGILL, /* Illegal instruction (ANSI). */ + "TRAP", SIGTRAP, /* Trace trap (POSIX). */ + "ABRT", SIGABRT, /* Abort (ANSI). */ + "IOT", SIGIOT, /* IOT trap (4.2 BSD). */ + "BUS", SIGBUS, /* BUS error (4.2 BSD). */ + "FPE", SIGFPE, /* Floating-point exception (ANSI). */ + "KILL", SIGKILL, /* Kill, unblockable (POSIX). */ + "USR1", SIGUSR1, /* User-defined signal 1 (POSIX). */ + "SEGV", SIGSEGV, /* Segmentation violation (ANSI). */ + "USR2", SIGUSR2, /* User-defined signal 2 (POSIX). */ + "PIPE", SIGPIPE, /* Broken pipe (POSIX). */ + "ALRM", SIGALRM, /* Alarm clock (POSIX). */ + "TERM", SIGTERM, /* Termination (ANSI). */ +#ifdef SIGSTKFLT + "STKFLT", SIGSTKFLT, /* Stack fault. */ +#endif + "CLD", SIGCLD, /* Same as SIGCHLD (System V). */ + "CHLD", SIGCHLD, /* Child status has changed (POSIX). */ + "CONT", SIGCONT, /* Continue (POSIX). */ + "STOP", SIGSTOP, /* Stop, unblockable (POSIX). */ + "TSTP", SIGTSTP, /* Keyboard stop (POSIX). */ + "TTIN", SIGTTIN, /* Background read from tty (POSIX). */ + "TTOU", SIGTTOU, /* Background write to tty (POSIX). */ + "URG", SIGURG, /* Urgent condition on socket (4.2 BSD). */ + "XCPU", SIGXCPU, /* CPU limit exceeded (4.2 BSD). */ + "XFSZ", SIGXFSZ, /* File size limit exceeded (4.2 BSD). */ + "DANGER", SIGDANGER, /* System crash imminent; free up some page space (AIX). */ + "VTALRM", SIGVTALRM, /* Virtual alarm clock (4.2 BSD). */ + "PROF", SIGPROF, /* Profiling alarm clock (4.2 BSD). */ + "WINCH", SIGWINCH, /* Window size change (4.3 BSD, Sun). */ + "POLL", SIGPOLL, /* Pollable event occurred (System V). */ + "IO", SIGIO, /* I/O now possible (4.2 BSD). */ + "PWR", SIGPWR, /* Power failure restart (System V). */ +#ifdef SIGSYS + "SYS", SIGSYS /* Bad system call. Only on some Linuxen! */ +#endif + }; + +JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name)) + + /* find and return the named signal's number */ + + for(uint i=0; i /* For DIR */ + +// Must redefine NULL because the macro gets redefined to int 0 +// by dirent.h. This redefinition is included later then the standard definition in +// globalDefinitions_.hpp and leads to assertions in the VM initialization. +// We definitely need NULL to have the same lengh as an address pointer. +#ifdef _LP64 +#undef NULL +#define NULL 0L +#else +#ifndef NULL +#define NULL 0 +#endif +#endif + +#include /* For MAXPATHLEN */ +#include /* For socklen_t */ +#include /* For F_OK, R_OK, W_OK */ + +#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"} +#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"} +#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"} +#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"} +#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"} +#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"} + +#define JNI_LIB_PREFIX "lib" +#define JNI_LIB_SUFFIX ".so" + +// Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may +// cause problems if JVM and the rest of JDK are built on different +// Linux releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1, +// so buffers declared in VM are always >= 4096. +#define JVM_MAXPATHLEN MAXPATHLEN + 1 + +#define JVM_R_OK R_OK +#define JVM_W_OK W_OK +#define JVM_X_OK X_OK +#define JVM_F_OK F_OK + +/* + * File I/O + */ + +#include +#include +#include +#include + +/* O Flags */ + +#define JVM_O_RDONLY O_RDONLY +#define JVM_O_WRONLY O_WRONLY +#define JVM_O_RDWR O_RDWR +#define JVM_O_O_APPEND O_APPEND +#define JVM_O_EXCL O_EXCL +#define JVM_O_CREAT O_CREAT + +/* Signal definitions */ + +#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ +#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ +#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ +#define SHUTDOWN2_SIGNAL SIGINT +#define SHUTDOWN3_SIGNAL SIGTERM + +#endif /* JVM_MD_H */ + +#endif // OS_AIX_VM_JVM_AIX_H diff --git a/hotspot/src/os/aix/vm/libperfstat_aix.cpp b/hotspot/src/os/aix/vm/libperfstat_aix.cpp new file mode 100644 index 00000000000..5b0d56c8bdf --- /dev/null +++ b/hotspot/src/os/aix/vm/libperfstat_aix.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/arguments.hpp" +#include "libperfstat_aix.hpp" + +// For dlopen and friends +#include + +// handle to the libperfstat +static void* g_libhandle = NULL; + +// whether initialization worked +static bool g_initialized = false; + + +typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, perfstat_cpu_total_t* userbuff, + int sizeof_userbuff, int desired_number); + +typedef int (*fun_perfstat_memory_total_t) (perfstat_id_t *name, perfstat_memory_total_t* userbuff, + int sizeof_userbuff, int desired_number); + +typedef void (*fun_perfstat_reset_t) (); + +static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL; +static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL; +static fun_perfstat_reset_t g_fun_perfstat_reset = NULL; + +bool libperfstat::init() { + + if (g_initialized) { + return true; + } + + g_initialized = false; + + // dynamically load the libperfstat porting library. + g_libhandle = dlopen("/usr/lib/libperfstat.a(shr_64.o)", RTLD_MEMBER | RTLD_NOW); + if (!g_libhandle) { + if (Verbose) { + fprintf(stderr, "Cannot load libperfstat.a (dlerror: %s)", dlerror()); + } + return false; + } + + // resolve function pointers + +#define RESOLVE_FUN_NO_ERROR(name) \ + g_fun_##name = (fun_##name##_t) dlsym(g_libhandle, #name); + +#define RESOLVE_FUN(name) \ + RESOLVE_FUN_NO_ERROR(name) \ + if (!g_fun_##name) { \ + if (Verbose) { \ + fprintf(stderr, "Cannot resolve " #name "() from libperfstat.a\n" \ + " (dlerror: %s)", dlerror()); \ + } \ + return false; \ + } + + RESOLVE_FUN(perfstat_cpu_total); + RESOLVE_FUN(perfstat_memory_total); + RESOLVE_FUN(perfstat_reset); + + g_initialized = true; + + return true; +} + +void libperfstat::cleanup() { + + g_initialized = false; + + if (g_libhandle) { + dlclose(g_libhandle); + g_libhandle = NULL; + } + + g_fun_perfstat_cpu_total = NULL; + g_fun_perfstat_memory_total = NULL; + g_fun_perfstat_reset = NULL; +} + +int libperfstat::perfstat_memory_total(perfstat_id_t *name, + perfstat_memory_total_t* userbuff, + int sizeof_userbuff, int desired_number) { + assert(g_initialized, "libperfstat not initialized"); + assert(g_fun_perfstat_memory_total, ""); + return g_fun_perfstat_memory_total(name, userbuff, sizeof_userbuff, desired_number); +} + +int libperfstat::perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff, + int sizeof_userbuff, int desired_number) { + assert(g_initialized, "libperfstat not initialized"); + assert(g_fun_perfstat_cpu_total, ""); + return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number); +} + +void libperfstat::perfstat_reset() { + assert(g_initialized, "libperfstat not initialized"); + assert(g_fun_perfstat_reset, ""); + g_fun_perfstat_reset(); +} diff --git a/hotspot/src/os/aix/vm/libperfstat_aix.hpp b/hotspot/src/os/aix/vm/libperfstat_aix.hpp new file mode 100644 index 00000000000..8d7b45da12f --- /dev/null +++ b/hotspot/src/os/aix/vm/libperfstat_aix.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// encapsulates the libperfstat library. +// +// The purpose of this code is to dynamically load the libperfstat library +// instead of statically linking against it. The libperfstat library is an +// AIX-specific library which only exists on AIX, not on PASE. If I want to +// share binaries between AIX and PASE, I cannot directly link against libperfstat.so. + +#ifndef OS_AIX_VM_LIBPERFSTAT_AIX_HPP +#define OS_AIX_VM_LIBPERFSTAT_AIX_HPP + +#include + +class libperfstat { + +public: + + // Load the libperfstat library (must be in LIBPATH). + // Returns true if succeeded, false if error. + static bool init(); + + // cleanup of the libo4 porting library. + static void cleanup(); + + // direct wrappers for the libperfstat functionality. All they do is + // to call the functions with the same name via function pointers. + static int perfstat_cpu_total(perfstat_id_t *name, perfstat_cpu_total_t* userbuff, + int sizeof_userbuff, int desired_number); + + static int perfstat_memory_total(perfstat_id_t *name, perfstat_memory_total_t* userbuff, + int sizeof_userbuff, int desired_number); + + static void perfstat_reset(); +}; + +#endif // OS_AIX_VM_LIBPERFSTAT_AIX_HPP diff --git a/hotspot/src/os/aix/vm/loadlib_aix.cpp b/hotspot/src/os/aix/vm/loadlib_aix.cpp new file mode 100644 index 00000000000..e62b5ffff7e --- /dev/null +++ b/hotspot/src/os/aix/vm/loadlib_aix.cpp @@ -0,0 +1,185 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +// Implementation of LoadedLibraries and friends + +// Ultimately this just uses loadquery() +// See: +// http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp +// ?topic=/com.ibm.aix.basetechref/doc/basetrf1/loadquery.htm + +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +// 'allocation.inline.hpp' triggers the inclusion of 'inttypes.h' which defines macros +// required by the definitions in 'globalDefinitions.hpp'. But these macros in 'inttypes.h' +// are only defined if '__STDC_FORMAT_MACROS' is defined! +#include "memory/allocation.inline.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/threadCritical.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" +#include "loadlib_aix.hpp" +#include "porting_aix.hpp" + +// For loadquery() +#include + +/////////////////////////////////////////////////////////////////////////////// +// Implementation for LoadedLibraryModule + +// output debug info +void LoadedLibraryModule::print(outputStream* os) const { + os->print("%15.15s: text: " INTPTR_FORMAT " - " INTPTR_FORMAT + ", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " ", + shortname, text_from, text_to, data_from, data_to); + os->print(" %s", fullpath); + if (strlen(membername) > 0) { + os->print("(%s)", membername); + } + os->cr(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Implementation for LoadedLibraries + +// class variables +LoadedLibraryModule LoadedLibraries::tab[MAX_MODULES]; +int LoadedLibraries::num_loaded = 0; + +// Checks whether the address p points to any of the loaded code segments. +// If it does, returns the LoadedLibraryModule entry. If not, returns NULL. +// static +const LoadedLibraryModule* LoadedLibraries::find_for_text_address(const unsigned char* p) { + + if (num_loaded == 0) { + reload(); + } + for (int i = 0; i < num_loaded; i++) { + if (tab[i].is_in_text(p)) { + return &tab[i]; + } + } + return NULL; +} + +// Checks whether the address p points to any of the loaded data segments. +// If it does, returns the LoadedLibraryModule entry. If not, returns NULL. +// static +const LoadedLibraryModule* LoadedLibraries::find_for_data_address(const unsigned char* p) { + if (num_loaded == 0) { + reload(); + } + for (int i = 0; i < num_loaded; i++) { + if (tab[i].is_in_data(p)) { + return &tab[i]; + } + } + return NULL; +} + +// Rebuild the internal table of LoadedLibraryModule objects +// static +void LoadedLibraries::reload() { + + ThreadCritical cs; + + // discard old content + num_loaded = 0; + + // Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. + size_t buf_size = 4096; + char* loadquery_buf = AllocateHeap(buf_size, mtInternal); + + while(loadquery(L_GETINFO, loadquery_buf, buf_size) == -1) { + if (errno == ENOMEM) { + buf_size *= 2; + loadquery_buf = ReallocateHeap(loadquery_buf, buf_size, mtInternal); + } else { + FreeHeap(loadquery_buf); + // Ensure that the uintptr_t pointer is valid + assert(errno != EFAULT, "loadquery: Invalid uintptr_t in info buffer."); + fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno)); + return; + } + } + + // Iterate over the loadquery result. For details see sys/ldr.h on AIX. + const struct ld_info* p = (struct ld_info*) loadquery_buf; + + // Ensure we have all loaded libs. + bool all_loaded = false; + while(num_loaded < MAX_MODULES) { + LoadedLibraryModule& mod = tab[num_loaded]; + mod.text_from = (const unsigned char*) p->ldinfo_textorg; + mod.text_to = (const unsigned char*) (((char*)p->ldinfo_textorg) + p->ldinfo_textsize); + mod.data_from = (const unsigned char*) p->ldinfo_dataorg; + mod.data_to = (const unsigned char*) (((char*)p->ldinfo_dataorg) + p->ldinfo_datasize); + sprintf(mod.fullpath, "%.*s", sizeof(mod.fullpath), p->ldinfo_filename); + // do we have a member name as well (see ldr.h)? + const char* p_mbr_name = p->ldinfo_filename + strlen(p->ldinfo_filename) + 1; + if (*p_mbr_name) { + sprintf(mod.membername, "%.*s", sizeof(mod.membername), p_mbr_name); + } else { + mod.membername[0] = '\0'; + } + + // fill in the short name + const char* p_slash = strrchr(mod.fullpath, '/'); + if (p_slash) { + sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), p_slash + 1); + } else { + sprintf(mod.shortname, "%.*s", sizeof(mod.shortname), mod.fullpath); + } + num_loaded ++; + + // next entry... + if (p->ldinfo_next) { + p = (struct ld_info*)(((char*)p) + p->ldinfo_next); + } else { + all_loaded = true; + break; + } + } + + FreeHeap(loadquery_buf); + + // Ensure we have all loaded libs + assert(all_loaded, "loadquery returned more entries then expected. Please increase MAX_MODULES"); + +} // end LoadedLibraries::reload() + + +// output loaded libraries table +//static +void LoadedLibraries::print(outputStream* os) { + + for (int i = 0; i < num_loaded; i++) { + tab[i].print(os); + } + +} + diff --git a/hotspot/src/os/aix/vm/loadlib_aix.hpp b/hotspot/src/os/aix/vm/loadlib_aix.hpp new file mode 100644 index 00000000000..2f6c2008f2a --- /dev/null +++ b/hotspot/src/os/aix/vm/loadlib_aix.hpp @@ -0,0 +1,128 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +// Loadlib_aix.cpp contains support code for analysing the memory +// layout of loaded binaries in ones own process space. +// +// It is needed, among other things, to provide a dladdr() emulation, because +// that one is not provided by AIX + +#ifndef OS_AIX_VM_LOADLIB_AIX_HPP +#define OS_AIX_VM_LOADLIB_AIX_HPP + +class outputStream; + +// This class holds information about a single loaded library module. +// Note that on AIX, a single library can be spread over multiple +// uintptr_t range on a module base, eg. +// libC.a(shr3_64.o) or libC.a(shrcore_64.o). +class LoadedLibraryModule { + + friend class LoadedLibraries; + + char fullpath[512]; // eg /usr/lib/libC.a + char shortname[30]; // eg libC.a + char membername[30]; // eg shrcore_64.o + const unsigned char* text_from; + const unsigned char* text_to; + const unsigned char* data_from; + const unsigned char* data_to; + + public: + + const char* get_fullpath() const { + return fullpath; + } + const char* get_shortname() const { + return shortname; + } + const char* get_membername() const { + return membername; + } + + // text_from, text_to: returns the range of the text (code) + // segment for that module + const unsigned char* get_text_from() const { + return text_from; + } + const unsigned char* get_text_to() const { + return text_to; + } + + // data_from/data_to: returns the range of the data + // segment for that module + const unsigned char* get_data_from() const { + return data_from; + } + const unsigned char* get_data_to() const { + return data_to; + } + + // returns true if the + bool is_in_text(const unsigned char* p) const { + return p >= text_from && p < text_to ? true : false; + } + + bool is_in_data(const unsigned char* p) const { + return p >= data_from && p < data_to ? true : false; + } + + // output debug info + void print(outputStream* os) const; + +}; // end LoadedLibraryModule + +// This class is a singleton holding a map of all loaded binaries +// in the AIX process space. +class LoadedLibraries +// : AllStatic (including allocation.hpp just for AllStatic is overkill.) +{ + + private: + + enum {MAX_MODULES = 100}; + static LoadedLibraryModule tab[MAX_MODULES]; + static int num_loaded; + + public: + + // rebuild the internal table of LoadedLibraryModule objects + static void reload(); + + // checks whether the address p points to any of the loaded code segments. + // If it does, returns the LoadedLibraryModule entry. If not, returns NULL. + static const LoadedLibraryModule* find_for_text_address(const unsigned char* p); + + // checks whether the address p points to any of the loaded data segments. + // If it does, returns the LoadedLibraryModule entry. If not, returns NULL. + static const LoadedLibraryModule* find_for_data_address(const unsigned char* p); + + // output debug info + static void print(outputStream* os); + +}; // end LoadedLibraries + + +#endif // OS_AIX_VM_LOADLIB_AIX_HPP diff --git a/hotspot/src/os/aix/vm/mutex_aix.inline.hpp b/hotspot/src/os/aix/vm/mutex_aix.inline.hpp new file mode 100644 index 00000000000..479032f7297 --- /dev/null +++ b/hotspot/src/os/aix/vm/mutex_aix.inline.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_MUTEX_AIX_INLINE_HPP +#define OS_AIX_VM_MUTEX_AIX_INLINE_HPP + +#include "os_aix.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "thread_aix.inline.hpp" + +#endif // OS_AIX_VM_MUTEX_AIX_INLINE_HPP diff --git a/hotspot/src/os/aix/vm/osThread_aix.cpp b/hotspot/src/os/aix/vm/osThread_aix.cpp new file mode 100644 index 00000000000..11f9c39168e --- /dev/null +++ b/hotspot/src/os/aix/vm/osThread_aix.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// no precompiled headers +#include "runtime/atomic.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/os.hpp" +#include "runtime/osThread.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/vmThread.hpp" +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +#endif + + +void OSThread::pd_initialize() { + assert(this != NULL, "check"); + _thread_id = 0; + _pthread_id = 0; + _siginfo = NULL; + _ucontext = NULL; + _expanding_stack = 0; + _alt_sig_stack = NULL; + + _last_cpu_times.sys = _last_cpu_times.user = 0L; + + sigemptyset(&_caller_sigmask); + + _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true); + assert(_startThread_lock !=NULL, "check"); +} + +void OSThread::pd_destroy() { + delete _startThread_lock; +} diff --git a/hotspot/src/os/aix/vm/osThread_aix.hpp b/hotspot/src/os/aix/vm/osThread_aix.hpp new file mode 100644 index 00000000000..a18943cd67d --- /dev/null +++ b/hotspot/src/os/aix/vm/osThread_aix.hpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_OSTHREAD_AIX_HPP +#define OS_AIX_VM_OSTHREAD_AIX_HPP + + public: + typedef pid_t thread_id_t; + + private: + int _thread_type; + + public: + + int thread_type() const { + return _thread_type; + } + void set_thread_type(int type) { + _thread_type = type; + } + + private: + + // _pthread_id is the pthread id, which is used by library calls + // (e.g. pthread_kill). + pthread_t _pthread_id; + + sigset_t _caller_sigmask; // Caller's signal mask + + public: + + // Methods to save/restore caller's signal mask + sigset_t caller_sigmask() const { return _caller_sigmask; } + void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; } + +#ifndef PRODUCT + // Used for debugging, return a unique integer for each thread. + int thread_identifier() const { return _thread_id; } +#endif +#ifdef ASSERT + // We expect no reposition failures so kill vm if we get one. + // + bool valid_reposition_failure() { + return false; + } +#endif // ASSERT + pthread_t pthread_id() const { + return _pthread_id; + } + void set_pthread_id(pthread_t tid) { + _pthread_id = tid; + } + + // *************************************************************** + // suspension support. + // *************************************************************** + + public: + // flags that support signal based suspend/resume on Linux are in a + // separate class to avoid confusion with many flags in OSThread that + // are used by VM level suspend/resume. + os::SuspendResume sr; + + // _ucontext and _siginfo are used by SR_handler() to save thread context, + // and they will later be used to walk the stack or reposition thread PC. + // If the thread is not suspended in SR_handler() (e.g. self suspend), + // the value in _ucontext is meaningless, so we must use the last Java + // frame information as the frame. This will mean that for threads + // that are parked on a mutex the profiler (and safepoint mechanism) + // will see the thread as if it were still in the Java frame. This + // not a problem for the profiler since the Java frame is a close + // enough result. For the safepoint mechanism when the give it the + // Java frame we are not at a point where the safepoint needs the + // frame to that accurate (like for a compiled safepoint) since we + // should be in a place where we are native and will block ourselves + // if we transition. + private: + void* _siginfo; + ucontext_t* _ucontext; + int _expanding_stack; // non zero if manually expanding stack + address _alt_sig_stack; // address of base of alternate signal stack + + public: + void* siginfo() const { return _siginfo; } + void set_siginfo(void* ptr) { _siginfo = ptr; } + ucontext_t* ucontext() const { return _ucontext; } + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; } + void set_expanding_stack(void) { _expanding_stack = 1; } + void clear_expanding_stack(void) { _expanding_stack = 0; } + int expanding_stack(void) { return _expanding_stack; } + + void set_alt_sig_stack(address val) { _alt_sig_stack = val; } + address alt_sig_stack(void) { return _alt_sig_stack; } + + private: + Monitor* _startThread_lock; // sync parent and child in thread creation + + public: + + Monitor* startThread_lock() const { + return _startThread_lock; + } + + // *************************************************************** + // Platform dependent initialization and cleanup + // *************************************************************** + + private: + + void pd_initialize(); + void pd_destroy(); + + public: + + // The last measured values of cpu timing to prevent the "stale + // value return" bug in thread_cpu_time. + volatile struct { + jlong sys; + jlong user; + } _last_cpu_times; + +#endif // OS_AIX_VM_OSTHREAD_AIX_HPP diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp new file mode 100644 index 00000000000..159ceb4ad1a --- /dev/null +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -0,0 +1,5126 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// According to the AIX OS doc #pragma alloca must be used +// with C++ compiler before referencing the function alloca() +#pragma alloca + +// no precompiled headers +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "compiler/compileBroker.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_aix.h" +#include "libperfstat_aix.hpp" +#include "loadlib_aix.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/filemap.hpp" +#include "mutex_aix.inline.hpp" +#include "oops/oop.inline.hpp" +#include "os_share_aix.hpp" +#include "porting_aix.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/globals.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/osThread.hpp" +#include "runtime/perfMemory.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/statSampler.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/threadCritical.hpp" +#include "runtime/timer.hpp" +#include "services/attachListener.hpp" +#include "services/runtimeService.hpp" +#include "thread_aix.inline.hpp" +#include "utilities/decoder.hpp" +#include "utilities/defaultStream.hpp" +#include "utilities/events.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/vmError.hpp" +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +# include "nativeInst_ppc.hpp" +#endif +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +// put OS-includes here (sorted alphabetically) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Add missing declarations (should be in procinfo.h but isn't until AIX 6.1). +#if !defined(_AIXVERSION_610) +extern "C" { + int getthrds64(pid_t ProcessIdentifier, + struct thrdentry64* ThreadBuffer, + int ThreadSize, + tid64_t* IndexPointer, + int Count); +} +#endif + +// Excerpts from systemcfg.h definitions newer than AIX 5.3 +#ifndef PV_7 +# define PV_7 0x200000 // Power PC 7 +# define PV_7_Compat 0x208000 // Power PC 7 +#endif + +#define MAX_PATH (2 * K) + +// for timer info max values which include all bits +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) +// for multipage initialization error analysis (in 'g_multipage_error') +#define ERROR_MP_OS_TOO_OLD 100 +#define ERROR_MP_EXTSHM_ACTIVE 101 +#define ERROR_MP_VMGETINFO_FAILED 102 +#define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103 + +// the semantics in this file are thus that codeptr_t is a *real code ptr* +// This means that any function taking codeptr_t as arguments will assume +// a real codeptr and won't handle function descriptors (eg getFuncName), +// whereas functions taking address as args will deal with function +// descriptors (eg os::dll_address_to_library_name) +typedef unsigned int* codeptr_t; + +// typedefs for stackslots, stack pointers, pointers to op codes +typedef unsigned long stackslot_t; +typedef stackslot_t* stackptr_t; + +// query dimensions of the stack of the calling thread +static void query_stack_dimensions(address* p_stack_base, size_t* p_stack_size); + +// function to check a given stack pointer against given stack limits +inline bool is_valid_stackpointer(stackptr_t sp, stackptr_t stack_base, size_t stack_size) { + if (((uintptr_t)sp) & 0x7) { + return false; + } + if (sp > stack_base) { + return false; + } + if (sp < (stackptr_t) ((address)stack_base - stack_size)) { + return false; + } + return true; +} + +// returns true if function is a valid codepointer +inline bool is_valid_codepointer(codeptr_t p) { + if (!p) { + return false; + } + if (((uintptr_t)p) & 0x3) { + return false; + } + if (LoadedLibraries::find_for_text_address((address)p) == NULL) { + return false; + } + return true; +} + +// macro to check a given stack pointer against given stack limits and to die if test fails +#define CHECK_STACK_PTR(sp, stack_base, stack_size) { \ + guarantee(is_valid_stackpointer((stackptr_t)(sp), (stackptr_t)(stack_base), stack_size), "Stack Pointer Invalid"); \ +} + +// macro to check the current stack pointer against given stacklimits +#define CHECK_CURRENT_STACK_PTR(stack_base, stack_size) { \ + address sp; \ + sp = os::current_stack_pointer(); \ + CHECK_STACK_PTR(sp, stack_base, stack_size); \ +} + +//////////////////////////////////////////////////////////////////////////////// +// global variables (for a description see os_aix.hpp) + +julong os::Aix::_physical_memory = 0; +pthread_t os::Aix::_main_thread = ((pthread_t)0); +int os::Aix::_page_size = -1; +int os::Aix::_on_pase = -1; +int os::Aix::_os_version = -1; +int os::Aix::_stack_page_size = -1; +size_t os::Aix::_shm_default_page_size = -1; +int os::Aix::_can_use_64K_pages = -1; +int os::Aix::_can_use_16M_pages = -1; +int os::Aix::_xpg_sus_mode = -1; +int os::Aix::_extshm = -1; +int os::Aix::_logical_cpus = -1; + +//////////////////////////////////////////////////////////////////////////////// +// local variables + +static int g_multipage_error = -1; // error analysis for multipage initialization +static jlong initial_time_count = 0; +static int clock_tics_per_sec = 100; +static sigset_t check_signal_done; // For diagnostics to print a message once (see run_periodic_checks) +static bool check_signals = true; +static pid_t _initial_pid = 0; +static int SR_signum = SIGUSR2; // Signal used to suspend/resume a thread (must be > SIGSEGV, see 4355769) +static sigset_t SR_sigset; +static pthread_mutex_t dl_mutex; // Used to protect dlsym() calls */ + +julong os::available_memory() { + return Aix::available_memory(); +} + +julong os::Aix::available_memory() { + Unimplemented(); + return 0; +} + +julong os::physical_memory() { + return Aix::physical_memory(); +} + +//////////////////////////////////////////////////////////////////////////////// +// environment support + +bool os::getenv(const char* name, char* buf, int len) { + const char* val = ::getenv(name); + if (val != NULL && strlen(val) < (size_t)len) { + strcpy(buf, val); + return true; + } + if (len > 0) buf[0] = 0; // return a null string + return false; +} + + +// Return true if user is running as root. + +bool os::have_special_privileges() { + static bool init = false; + static bool privileges = false; + if (!init) { + privileges = (getuid() != geteuid()) || (getgid() != getegid()); + init = true; + } + return privileges; +} + +// Helper function, emulates disclaim64 using multiple 32bit disclaims +// because we cannot use disclaim64() on AS/400 and old AIX releases. +static bool my_disclaim64(char* addr, size_t size) { + + if (size == 0) { + return true; + } + + // Maximum size 32bit disclaim() accepts. (Theoretically 4GB, but I just do not trust that.) + const unsigned int maxDisclaimSize = 0x80000000; + + const unsigned int numFullDisclaimsNeeded = (size / maxDisclaimSize); + const unsigned int lastDisclaimSize = (size % maxDisclaimSize); + + char* p = addr; + + for (int i = 0; i < numFullDisclaimsNeeded; i ++) { + if (::disclaim(p, maxDisclaimSize, DISCLAIM_ZEROMEM) != 0) { + //if (Verbose) + fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno); + return false; + } + p += maxDisclaimSize; + } + + if (lastDisclaimSize > 0) { + if (::disclaim(p, lastDisclaimSize, DISCLAIM_ZEROMEM) != 0) { + //if (Verbose) + fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno); + return false; + } + } + + return true; +} + +// Cpu architecture string +#if defined(PPC32) +static char cpu_arch[] = "ppc"; +#elif defined(PPC64) +static char cpu_arch[] = "ppc64"; +#else +#error Add appropriate cpu_arch setting +#endif + + +// Given an address, returns the size of the page backing that address. +size_t os::Aix::query_pagesize(void* addr) { + + vm_page_info pi; + pi.addr = (uint64_t)addr; + if (::vmgetinfo(&pi, VM_PAGE_INFO, sizeof(pi)) == 0) { + return pi.pagesize; + } else { + fprintf(stderr, "vmgetinfo failed to retrieve page size for address %p (errno %d).\n", addr, errno); + assert(false, "vmgetinfo failed to retrieve page size"); + return SIZE_4K; + } + +} + +// Returns the kernel thread id of the currently running thread. +pid_t os::Aix::gettid() { + return (pid_t) thread_self(); +} + +void os::Aix::initialize_system_info() { + + // get the number of online(logical) cpus instead of configured + os::_processor_count = sysconf(_SC_NPROCESSORS_ONLN); + assert(_processor_count > 0, "_processor_count must be > 0"); + + // retrieve total physical storage + os::Aix::meminfo_t mi; + if (!os::Aix::get_meminfo(&mi)) { + fprintf(stderr, "os::Aix::get_meminfo failed.\n"); fflush(stderr); + assert(false, "os::Aix::get_meminfo failed."); + } + _physical_memory = (julong) mi.real_total; +} + +// Helper function for tracing page sizes. +static const char* describe_pagesize(size_t pagesize) { + switch (pagesize) { + case SIZE_4K : return "4K"; + case SIZE_64K: return "64K"; + case SIZE_16M: return "16M"; + case SIZE_16G: return "16G"; + default: + assert(false, "surprise"); + return "??"; + } +} + +// Retrieve information about multipage size support. Will initialize +// Aix::_page_size, Aix::_stack_page_size, Aix::_can_use_64K_pages, +// Aix::_can_use_16M_pages. +// Must be called before calling os::large_page_init(). +void os::Aix::query_multipage_support() { + + guarantee(_page_size == -1 && + _stack_page_size == -1 && + _can_use_64K_pages == -1 && + _can_use_16M_pages == -1 && + g_multipage_error == -1, + "do not call twice"); + + _page_size = ::sysconf(_SC_PAGESIZE); + + // This really would surprise me. + assert(_page_size == SIZE_4K, "surprise!"); + + + // query default data page size (default page size for C-Heap, pthread stacks and .bss). + // Default data page size is influenced either by linker options (-bdatapsize) + // or by environment variable LDR_CNTRL (suboption DATAPSIZE). If none is given, + // default should be 4K. + size_t data_page_size = SIZE_4K; + { + void* p = ::malloc(SIZE_16M); + data_page_size = os::Aix::query_pagesize(p); + ::free(p); + } + + // query default shm page size (LDR_CNTRL SHMPSIZE) + { + const int shmid = ::shmget(IPC_PRIVATE, 1, IPC_CREAT | S_IRUSR | S_IWUSR); + guarantee(shmid != -1, "shmget failed"); + void* p = ::shmat(shmid, NULL, 0); + ::shmctl(shmid, IPC_RMID, NULL); + guarantee(p != (void*) -1, "shmat failed"); + _shm_default_page_size = os::Aix::query_pagesize(p); + ::shmdt(p); + } + + // before querying the stack page size, make sure we are not running as primordial + // thread (because primordial thread's stack may have different page size than + // pthread thread stacks). Running a VM on the primordial thread won't work for a + // number of reasons so we may just as well guarantee it here + guarantee(!os::Aix::is_primordial_thread(), "Must not be called for primordial thread"); + + // query stack page size + { + int dummy = 0; + _stack_page_size = os::Aix::query_pagesize(&dummy); + // everything else would surprise me and should be looked into + guarantee(_stack_page_size == SIZE_4K || _stack_page_size == SIZE_64K, "Wrong page size"); + // also, just for completeness: pthread stacks are allocated from C heap, so + // stack page size should be the same as data page size + guarantee(_stack_page_size == data_page_size, "stack page size should be the same as data page size"); + } + + // EXTSHM is bad: among other things, it prevents setting pagesize dynamically + // for system V shm. + if (Aix::extshm()) { + if (Verbose) { + fprintf(stderr, "EXTSHM is active - will disable large page support.\n" + "Please make sure EXTSHM is OFF for large page support.\n"); + } + g_multipage_error = ERROR_MP_EXTSHM_ACTIVE; + _can_use_64K_pages = _can_use_16M_pages = 0; + goto query_multipage_support_end; + } + + // now check which page sizes the OS claims it supports, and of those, which actually can be used. + { + const int MAX_PAGE_SIZES = 4; + psize_t sizes[MAX_PAGE_SIZES]; + const int num_psizes = ::vmgetinfo(sizes, VMINFO_GETPSIZES, MAX_PAGE_SIZES); + if (num_psizes == -1) { + if (Verbose) { + fprintf(stderr, "vmgetinfo(VMINFO_GETPSIZES) failed (errno: %d)\n", errno); + fprintf(stderr, "disabling multipage support.\n"); + } + g_multipage_error = ERROR_MP_VMGETINFO_FAILED; + _can_use_64K_pages = _can_use_16M_pages = 0; + goto query_multipage_support_end; + } + guarantee(num_psizes > 0, "vmgetinfo(.., VMINFO_GETPSIZES, ...) failed."); + assert(num_psizes <= MAX_PAGE_SIZES, "Surprise! more than 4 page sizes?"); + if (Verbose) { + fprintf(stderr, "vmgetinfo(.., VMINFO_GETPSIZES, ...) returns %d supported page sizes: ", num_psizes); + for (int i = 0; i < num_psizes; i ++) { + fprintf(stderr, " %s ", describe_pagesize(sizes[i])); + } + fprintf(stderr, " .\n"); + } + + // Can we use 64K, 16M pages? + _can_use_64K_pages = 0; + _can_use_16M_pages = 0; + for (int i = 0; i < num_psizes; i ++) { + if (sizes[i] == SIZE_64K) { + _can_use_64K_pages = 1; + } else if (sizes[i] == SIZE_16M) { + _can_use_16M_pages = 1; + } + } + + if (!_can_use_64K_pages) { + g_multipage_error = ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K; + } + + // Double-check for 16M pages: Even if AIX claims to be able to use 16M pages, + // there must be an actual 16M page pool, and we must run with enough rights. + if (_can_use_16M_pages) { + const int shmid = ::shmget(IPC_PRIVATE, SIZE_16M, IPC_CREAT | S_IRUSR | S_IWUSR); + guarantee(shmid != -1, "shmget failed"); + struct shmid_ds shm_buf = { 0 }; + shm_buf.shm_pagesize = SIZE_16M; + const bool can_set_pagesize = ::shmctl(shmid, SHM_PAGESIZE, &shm_buf) == 0 ? true : false; + const int en = errno; + ::shmctl(shmid, IPC_RMID, NULL); + if (!can_set_pagesize) { + if (Verbose) { + fprintf(stderr, "Failed to allocate even one misely 16M page. shmctl failed with %d (%s).\n" + "Will deactivate 16M support.\n", en, strerror(en)); + } + _can_use_16M_pages = 0; + } + } + + } // end: check which pages can be used for shared memory + +query_multipage_support_end: + + guarantee(_page_size != -1 && + _stack_page_size != -1 && + _can_use_64K_pages != -1 && + _can_use_16M_pages != -1, "Page sizes not properly initialized"); + + if (_can_use_64K_pages) { + g_multipage_error = 0; + } + + if (Verbose) { + fprintf(stderr, "Data page size (C-Heap, bss, etc): %s\n", describe_pagesize(data_page_size)); + fprintf(stderr, "Thread stack page size (pthread): %s\n", describe_pagesize(_stack_page_size)); + fprintf(stderr, "Default shared memory page size: %s\n", describe_pagesize(_shm_default_page_size)); + fprintf(stderr, "Can use 64K pages dynamically with shared meory: %s\n", (_can_use_64K_pages ? "yes" :"no")); + fprintf(stderr, "Can use 16M pages dynamically with shared memory: %s\n", (_can_use_16M_pages ? "yes" :"no")); + fprintf(stderr, "Multipage error details: %d\n", g_multipage_error); + } + +} // end os::Aix::query_multipage_support() + + +// The code for this method was initially derived from the version in os_linux.cpp +void os::init_system_properties_values() { + // The next few definitions allow the code to be verbatim: +#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal) +#define DEFAULT_LIBPATH "/usr/lib:/lib" +#define EXTENSIONS_DIR "/lib/ext" +#define ENDORSED_DIR "/lib/endorsed" + + // sysclasspath, java_home, dll_dir + char *home_path; + char *dll_path; + char *pslash; + char buf[MAXPATHLEN]; + os::jvm_path(buf, sizeof(buf)); + + // Found the full path to libjvm.so. + // Now cut the path to /jre if we can. + *(strrchr(buf, '/')) = '\0'; // get rid of /libjvm.so + pslash = strrchr(buf, '/'); + if (pslash != NULL) { + *pslash = '\0'; // get rid of /{client|server|hotspot} + } + + dll_path = malloc(strlen(buf) + 1); + strcpy(dll_path, buf); + Arguments::set_dll_dir(dll_path); + + if (pslash != NULL) { + pslash = strrchr(buf, '/'); + if (pslash != NULL) { + *pslash = '\0'; // get rid of / + pslash = strrchr(buf, '/'); + if (pslash != NULL) { + *pslash = '\0'; // get rid of /lib + } + } + } + + home_path = malloc(strlen(buf) + 1); + strcpy(home_path, buf); + Arguments::set_java_home(home_path); + + if (!set_boot_path('/', ':')) return; + + // Where to look for native libraries + + // On Aix we get the user setting of LIBPATH + // Eventually, all the library path setting will be done here. + char *ld_library_path; + + // Construct the invariant part of ld_library_path. + ld_library_path = (char *) malloc(sizeof(DEFAULT_LIBPATH)); + sprintf(ld_library_path, DEFAULT_LIBPATH); + + // Get the user setting of LIBPATH, and prepended it. + char *v = ::getenv("LIBPATH"); + if (v == NULL) { + v = ""; + } + + char *t = ld_library_path; + // That's +1 for the colon and +1 for the trailing '\0' + ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1); + sprintf(ld_library_path, "%s:%s", v, t); + + Arguments::set_library_path(ld_library_path); + + // Extensions directories + char* cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(EXTENSIONS_DIR)); + sprintf(cbuf, "%s" EXTENSIONS_DIR, Arguments::get_java_home()); + Arguments::set_ext_dirs(cbuf); + + // Endorsed standards default directory. + cbuf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR)); + sprintf(cbuf, "%s" ENDORSED_DIR, Arguments::get_java_home()); + Arguments::set_endorsed_dirs(cbuf); + +#undef malloc +#undef DEFAULT_LIBPATH +#undef EXTENSIONS_DIR +#undef ENDORSED_DIR +} + +//////////////////////////////////////////////////////////////////////////////// +// breakpoint support + +void os::breakpoint() { + BREAKPOINT; +} + +extern "C" void breakpoint() { + // use debugger to set breakpoint here +} + +//////////////////////////////////////////////////////////////////////////////// +// signal support + +debug_only(static bool signal_sets_initialized = false); +static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; + +bool os::Aix::is_sig_ignored(int sig) { + struct sigaction oact; + sigaction(sig, (struct sigaction*)NULL, &oact); + void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oact.sa_handler); + if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) + return true; + else + return false; +} + +void os::Aix::signal_sets_init() { + // Should also have an assertion stating we are still single-threaded. + assert(!signal_sets_initialized, "Already initialized"); + // Fill in signals that are necessarily unblocked for all threads in + // the VM. Currently, we unblock the following signals: + // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden + // by -Xrs (=ReduceSignalUsage)); + // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all + // other threads. The "ReduceSignalUsage" boolean tells us not to alter + // the dispositions or masks wrt these signals. + // Programs embedding the VM that want to use the above signals for their + // own purposes must, at this time, use the "-Xrs" option to prevent + // interference with shutdown hooks and BREAK_SIGNAL thread dumping. + // (See bug 4345157, and other related bugs). + // In reality, though, unblocking these signals is really a nop, since + // these signals are not blocked by default. + sigemptyset(&unblocked_sigs); + sigemptyset(&allowdebug_blocked_sigs); + sigaddset(&unblocked_sigs, SIGILL); + sigaddset(&unblocked_sigs, SIGSEGV); + sigaddset(&unblocked_sigs, SIGBUS); + sigaddset(&unblocked_sigs, SIGFPE); + sigaddset(&unblocked_sigs, SIGTRAP); + sigaddset(&unblocked_sigs, SIGDANGER); + sigaddset(&unblocked_sigs, SR_signum); + + if (!ReduceSignalUsage) { + if (!os::Aix::is_sig_ignored(SHUTDOWN1_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); + } + if (!os::Aix::is_sig_ignored(SHUTDOWN2_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); + } + if (!os::Aix::is_sig_ignored(SHUTDOWN3_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); + } + } + // Fill in signals that are blocked by all but the VM thread. + sigemptyset(&vm_sigs); + if (!ReduceSignalUsage) + sigaddset(&vm_sigs, BREAK_SIGNAL); + debug_only(signal_sets_initialized = true); +} + +// These are signals that are unblocked while a thread is running Java. +// (For some reason, they get blocked by default.) +sigset_t* os::Aix::unblocked_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &unblocked_sigs; +} + +// These are the signals that are blocked while a (non-VM) thread is +// running Java. Only the VM thread handles these signals. +sigset_t* os::Aix::vm_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &vm_sigs; +} + +// These are signals that are blocked during cond_wait to allow debugger in +sigset_t* os::Aix::allowdebug_blocked_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &allowdebug_blocked_sigs; +} + +void os::Aix::hotspot_sigmask(Thread* thread) { + + //Save caller's signal mask before setting VM signal mask + sigset_t caller_sigmask; + pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); + + OSThread* osthread = thread->osthread(); + osthread->set_caller_sigmask(caller_sigmask); + + pthread_sigmask(SIG_UNBLOCK, os::Aix::unblocked_signals(), NULL); + + if (!ReduceSignalUsage) { + if (thread->is_VM_thread()) { + // Only the VM thread handles BREAK_SIGNAL ... + pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL); + } else { + // ... all other threads block BREAK_SIGNAL + pthread_sigmask(SIG_BLOCK, vm_signals(), NULL); + } + } +} + +// retrieve memory information. +// Returns false if something went wrong; +// content of pmi undefined in this case. +bool os::Aix::get_meminfo(meminfo_t* pmi) { + + assert(pmi, "get_meminfo: invalid parameter"); + + memset(pmi, 0, sizeof(meminfo_t)); + + if (os::Aix::on_pase()) { + + Unimplemented(); + return false; + + } else { + + // On AIX, I use the (dynamically loaded) perfstat library to retrieve memory statistics + // See: + // http://publib.boulder.ibm.com/infocenter/systems/index.jsp + // ?topic=/com.ibm.aix.basetechref/doc/basetrf1/perfstat_memtot.htm + // http://publib.boulder.ibm.com/infocenter/systems/index.jsp + // ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm + + perfstat_memory_total_t psmt; + memset (&psmt, '\0', sizeof(psmt)); + const int rc = libperfstat::perfstat_memory_total(NULL, &psmt, sizeof(psmt), 1); + if (rc == -1) { + fprintf(stderr, "perfstat_memory_total() failed (errno=%d)\n", errno); + assert(0, "perfstat_memory_total() failed"); + return false; + } + + assert(rc == 1, "perfstat_memory_total() - weird return code"); + + // excerpt from + // http://publib.boulder.ibm.com/infocenter/systems/index.jsp + // ?topic=/com.ibm.aix.files/doc/aixfiles/libperfstat.h.htm + // The fields of perfstat_memory_total_t: + // u_longlong_t virt_total Total virtual memory (in 4 KB pages). + // u_longlong_t real_total Total real memory (in 4 KB pages). + // u_longlong_t real_free Free real memory (in 4 KB pages). + // u_longlong_t pgsp_total Total paging space (in 4 KB pages). + // u_longlong_t pgsp_free Free paging space (in 4 KB pages). + + pmi->virt_total = psmt.virt_total * 4096; + pmi->real_total = psmt.real_total * 4096; + pmi->real_free = psmt.real_free * 4096; + pmi->pgsp_total = psmt.pgsp_total * 4096; + pmi->pgsp_free = psmt.pgsp_free * 4096; + + return true; + + } +} // end os::Aix::get_meminfo + +// Retrieve global cpu information. +// Returns false if something went wrong; +// the content of pci is undefined in this case. +bool os::Aix::get_cpuinfo(cpuinfo_t* pci) { + assert(pci, "get_cpuinfo: invalid parameter"); + memset(pci, 0, sizeof(cpuinfo_t)); + + perfstat_cpu_total_t psct; + memset (&psct, '\0', sizeof(psct)); + + if (-1 == libperfstat::perfstat_cpu_total(NULL, &psct, sizeof(perfstat_cpu_total_t), 1)) { + fprintf(stderr, "perfstat_cpu_total() failed (errno=%d)\n", errno); + assert(0, "perfstat_cpu_total() failed"); + return false; + } + + // global cpu information + strcpy (pci->description, psct.description); + pci->processorHZ = psct.processorHZ; + pci->ncpus = psct.ncpus; + os::Aix::_logical_cpus = psct.ncpus; + for (int i = 0; i < 3; i++) { + pci->loadavg[i] = (double) psct.loadavg[i] / (1 << SBITS); + } + + // get the processor version from _system_configuration + switch (_system_configuration.version) { + case PV_7: + strcpy(pci->version, "Power PC 7"); + break; + case PV_6_1: + strcpy(pci->version, "Power PC 6 DD1.x"); + break; + case PV_6: + strcpy(pci->version, "Power PC 6"); + break; + case PV_5: + strcpy(pci->version, "Power PC 5"); + break; + case PV_5_2: + strcpy(pci->version, "Power PC 5_2"); + break; + case PV_5_3: + strcpy(pci->version, "Power PC 5_3"); + break; + case PV_5_Compat: + strcpy(pci->version, "PV_5_Compat"); + break; + case PV_6_Compat: + strcpy(pci->version, "PV_6_Compat"); + break; + case PV_7_Compat: + strcpy(pci->version, "PV_7_Compat"); + break; + default: + strcpy(pci->version, "unknown"); + } + + return true; + +} //end os::Aix::get_cpuinfo + +////////////////////////////////////////////////////////////////////////////// +// detecting pthread library + +void os::Aix::libpthread_init() { + return; +} + +////////////////////////////////////////////////////////////////////////////// +// create new thread + +// Thread start routine for all newly created threads +static void *java_start(Thread *thread) { + + // find out my own stack dimensions + { + // actually, this should do exactly the same as thread->record_stack_base_and_size... + address base = 0; + size_t size = 0; + query_stack_dimensions(&base, &size); + thread->set_stack_base(base); + thread->set_stack_size(size); + } + + // Do some sanity checks. + CHECK_CURRENT_STACK_PTR(thread->stack_base(), thread->stack_size()); + + // Try to randomize the cache line index of hot stack frames. + // This helps when threads of the same stack traces evict each other's + // cache lines. The threads can be either from the same JVM instance, or + // from different JVM instances. The benefit is especially true for + // processors with hyperthreading technology. + + static int counter = 0; + int pid = os::current_process_id(); + alloca(((pid ^ counter++) & 7) * 128); + + ThreadLocalStorage::set_thread(thread); + + OSThread* osthread = thread->osthread(); + + // thread_id is kernel thread id (similar to Solaris LWP id) + osthread->set_thread_id(os::Aix::gettid()); + + // initialize signal mask for this thread + os::Aix::hotspot_sigmask(thread); + + // initialize floating point control register + os::Aix::init_thread_fpu_state(); + + assert(osthread->get_state() == RUNNABLE, "invalid os thread state"); + + // call one more level start routine + thread->run(); + + return 0; +} + +bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { + + // We want the whole function to be synchronized. + ThreadCritical cs; + + assert(thread->osthread() == NULL, "caller responsible"); + + // Allocate the OSThread object + OSThread* osthread = new OSThread(NULL, NULL); + if (osthread == NULL) { + return false; + } + + // set the correct thread state + osthread->set_thread_type(thr_type); + + // Initial state is ALLOCATED but not INITIALIZED + osthread->set_state(ALLOCATED); + + thread->set_osthread(osthread); + + // init thread attributes + pthread_attr_t attr; + pthread_attr_init(&attr); + guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???"); + + // Make sure we run in 1:1 kernel-user-thread mode. + if (os::Aix::on_aix()) { + guarantee(pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0, "???"); + guarantee(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0, "???"); + } // end: aix + + // Start in suspended state, and in os::thread_start, wake the thread up. + guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???"); + + // calculate stack size if it's not specified by caller + if (os::Aix::supports_variable_stack_size()) { + if (stack_size == 0) { + stack_size = os::Aix::default_stack_size(thr_type); + + switch (thr_type) { + case os::java_thread: + // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss. + assert(JavaThread::stack_size_at_create() > 0, "this should be set"); + stack_size = JavaThread::stack_size_at_create(); + break; + case os::compiler_thread: + if (CompilerThreadStackSize > 0) { + stack_size = (size_t)(CompilerThreadStackSize * K); + break; + } // else fall through: + // use VMThreadStackSize if CompilerThreadStackSize is not defined + case os::vm_thread: + case os::pgc_thread: + case os::cgc_thread: + case os::watcher_thread: + if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); + break; + } + } + + stack_size = MAX2(stack_size, os::Aix::min_stack_allowed); + pthread_attr_setstacksize(&attr, stack_size); + } //else let thread_create() pick the default value (96 K on AIX) + + pthread_t tid; + int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + + pthread_attr_destroy(&attr); + + if (ret != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) { + perror("pthread_create()"); + } + // Need to clean up stuff we've allocated so far + thread->set_osthread(NULL); + delete osthread; + return false; + } + + // Store pthread info into the OSThread + osthread->set_pthread_id(tid); + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// attach existing thread + +// bootstrap the main thread +bool os::create_main_thread(JavaThread* thread) { + assert(os::Aix::_main_thread == pthread_self(), "should be called inside main thread"); + return create_attached_thread(thread); +} + +bool os::create_attached_thread(JavaThread* thread) { +#ifdef ASSERT + thread->verify_not_published(); +#endif + + // Allocate the OSThread object + OSThread* osthread = new OSThread(NULL, NULL); + + if (osthread == NULL) { + return false; + } + + // Store pthread info into the OSThread + osthread->set_thread_id(os::Aix::gettid()); + osthread->set_pthread_id(::pthread_self()); + + // initialize floating point control register + os::Aix::init_thread_fpu_state(); + + // some sanity checks + CHECK_CURRENT_STACK_PTR(thread->stack_base(), thread->stack_size()); + + // Initial thread state is RUNNABLE + osthread->set_state(RUNNABLE); + + thread->set_osthread(osthread); + + if (UseNUMA) { + int lgrp_id = os::numa_get_group_id(); + if (lgrp_id != -1) { + thread->set_lgrp_id(lgrp_id); + } + } + + // initialize signal mask for this thread + // and save the caller's signal mask + os::Aix::hotspot_sigmask(thread); + + return true; +} + +void os::pd_start_thread(Thread* thread) { + int status = pthread_continue_np(thread->osthread()->pthread_id()); + assert(status == 0, "thr_continue failed"); +} + +// Free OS resources related to the OSThread +void os::free_thread(OSThread* osthread) { + assert(osthread != NULL, "osthread not set"); + + if (Thread::current()->osthread() == osthread) { + // Restore caller's signal mask + sigset_t sigmask = osthread->caller_sigmask(); + pthread_sigmask(SIG_SETMASK, &sigmask, NULL); + } + + delete osthread; +} + +////////////////////////////////////////////////////////////////////////////// +// thread local storage + +int os::allocate_thread_local_storage() { + pthread_key_t key; + int rslt = pthread_key_create(&key, NULL); + assert(rslt == 0, "cannot allocate thread local storage"); + return (int)key; +} + +// Note: This is currently not used by VM, as we don't destroy TLS key +// on VM exit. +void os::free_thread_local_storage(int index) { + int rslt = pthread_key_delete((pthread_key_t)index); + assert(rslt == 0, "invalid index"); +} + +void os::thread_local_storage_at_put(int index, void* value) { + int rslt = pthread_setspecific((pthread_key_t)index, value); + assert(rslt == 0, "pthread_setspecific failed"); +} + +extern "C" Thread* get_thread() { + return ThreadLocalStorage::thread(); +} + +//////////////////////////////////////////////////////////////////////////////// +// time support + +// Time since start-up in seconds to a fine granularity. +// Used by VMSelfDestructTimer and the MemProfiler. +double os::elapsedTime() { + return (double)(os::elapsed_counter()) * 0.000001; +} + +jlong os::elapsed_counter() { + timeval time; + int status = gettimeofday(&time, NULL); + return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; +} + +jlong os::elapsed_frequency() { + return (1000 * 1000); +} + +// For now, we say that linux does not support vtime. I have no idea +// whether it can actually be made to (DLD, 9/13/05). + +bool os::supports_vtime() { return false; } +bool os::enable_vtime() { return false; } +bool os::vtime_enabled() { return false; } +double os::elapsedVTime() { + // better than nothing, but not much + return elapsedTime(); +} + +jlong os::javaTimeMillis() { + timeval time; + int status = gettimeofday(&time, NULL); + assert(status != -1, "aix error at gettimeofday()"); + return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); +} + +// We need to manually declare mread_real_time, +// because IBM didn't provide a prototype in time.h. +// (they probably only ever tested in C, not C++) +extern "C" +int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t); + +jlong os::javaTimeNanos() { + if (os::Aix::on_pase()) { + Unimplemented(); + return 0; + } + else { + // On AIX use the precision of processors real time clock + // or time base registers. + timebasestruct_t time; + int rc; + + // If the CPU has a time register, it will be used and + // we have to convert to real time first. After convertion we have following data: + // time.tb_high [seconds since 00:00:00 UTC on 1.1.1970] + // time.tb_low [nanoseconds after the last full second above] + // We better use mread_real_time here instead of read_real_time + // to ensure that we will get a monotonic increasing time. + if (mread_real_time(&time, TIMEBASE_SZ) != RTC_POWER) { + rc = time_base_to_time(&time, TIMEBASE_SZ); + assert(rc != -1, "aix error at time_base_to_time()"); + } + return jlong(time.tb_high) * (1000 * 1000 * 1000) + jlong(time.tb_low); + } +} + +void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { + { + // gettimeofday - based on time in seconds since the Epoch thus does not wrap + info_ptr->max_value = ALL_64_BITS; + + // gettimeofday is a real time clock so it skips + info_ptr->may_skip_backward = true; + info_ptr->may_skip_forward = true; + } + + info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time +} + +// Return the real, user, and system times in seconds from an +// arbitrary fixed point in the past. +bool os::getTimesSecs(double* process_real_time, + double* process_user_time, + double* process_system_time) { + Unimplemented(); + return false; +} + + +char * os::local_time_string(char *buf, size_t buflen) { + struct tm t; + time_t long_time; + time(&long_time); + localtime_r(&long_time, &t); + jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d", + t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, + t.tm_hour, t.tm_min, t.tm_sec); + return buf; +} + +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + return localtime_r(clock, res); +} + +//////////////////////////////////////////////////////////////////////////////// +// runtime exit support + +// Note: os::shutdown() might be called very early during initialization, or +// called from signal handler. Before adding something to os::shutdown(), make +// sure it is async-safe and can handle partially initialized VM. +void os::shutdown() { + + // allow PerfMemory to attempt cleanup of any persistent resources + perfMemory_exit(); + + // needs to remove object in file system + AttachListener::abort(); + + // flush buffered output, finish log files + ostream_abort(); + + // Check for abort hook + abort_hook_t abort_hook = Arguments::abort_hook(); + if (abort_hook != NULL) { + abort_hook(); + } + +} + +// Note: os::abort() might be called very early during initialization, or +// called from signal handler. Before adding something to os::abort(), make +// sure it is async-safe and can handle partially initialized VM. +void os::abort(bool dump_core) { + os::shutdown(); + if (dump_core) { +#ifndef PRODUCT + fdStream out(defaultStream::output_fd()); + out.print_raw("Current thread is "); + char buf[16]; + jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id()); + out.print_raw_cr(buf); + out.print_raw_cr("Dumping core ..."); +#endif + ::abort(); // dump core + } + + ::exit(1); +} + +// Die immediately, no exit hook, no abort hook, no cleanup. +void os::die() { + ::abort(); +} + +// Unused on Aix for now. +void os::set_error_file(const char *logfile) {} + + +// This method is a copy of JDK's sysGetLastErrorString +// from src/solaris/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + + if (errno == 0) return 0; + + const char *s = ::strerror(errno); + size_t n = ::strlen(s); + if (n >= len) { + n = len - 1; + } + ::strncpy(buf, s, n); + buf[n] = '\0'; + return n; +} + +intx os::current_thread_id() { return (intx)pthread_self(); } +int os::current_process_id() { + + // This implementation returns a unique pid, the pid of the + // launcher thread that starts the vm 'process'. + + // Under POSIX, getpid() returns the same pid as the + // launcher thread rather than a unique pid per thread. + // Use gettid() if you want the old pre NPTL behaviour. + + // if you are looking for the result of a call to getpid() that + // returns a unique pid for the calling thread, then look at the + // OSThread::thread_id() method in osThread_linux.hpp file + + return (int)(_initial_pid ? _initial_pid : getpid()); +} + +// DLL functions + +const char* os::dll_file_extension() { return ".so"; } + +// This must be hard coded because it's the system's temporary +// directory not the java application's temp directory, ala java.io.tmpdir. +const char* os::get_temp_directory() { return "/tmp"; } + +static bool file_exists(const char* filename) { + struct stat statbuf; + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return os::stat(filename, &statbuf) == 0; +} + +bool os::dll_build_name(char* buffer, size_t buflen, + const char* pname, const char* fname) { + bool retval = false; + // Copied from libhpi + const size_t pnamelen = pname ? strlen(pname) : 0; + + // Return error on buffer overflow. + if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { + *buffer = '\0'; + return retval; + } + + if (pnamelen == 0) { + snprintf(buffer, buflen, "lib%s.so", fname); + retval = true; + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0; i < n; i++) { + // Really shouldn't be NULL, but check can't hurt + if (pelements[i] == NULL || strlen(pelements[i]) == 0) { + continue; // skip the empty path values + } + snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); + if (file_exists(buffer)) { + retval = true; + break; + } + } + // release the storage + for (int i = 0; i < n; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements, mtInternal); + } + } else { + snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); + retval = true; + } + return retval; +} + +// Check if addr is inside libjvm.so. +bool os::address_is_in_vm(address addr) { + + // Input could be a real pc or a function pointer literal. The latter + // would be a function descriptor residing in the data segment of a module. + + const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(addr); + if (lib) { + if (strcmp(lib->get_shortname(), "libjvm.so") == 0) { + return true; + } else { + return false; + } + } else { + lib = LoadedLibraries::find_for_data_address(addr); + if (lib) { + if (strcmp(lib->get_shortname(), "libjvm.so") == 0) { + return true; + } else { + return false; + } + } else { + return false; + } + } +} + +// Resolve an AIX function descriptor literal to a code pointer. +// If the input is a valid code pointer to a text segment of a loaded module, +// it is returned unchanged. +// If the input is a valid AIX function descriptor, it is resolved to the +// code entry point. +// If the input is neither a valid function descriptor nor a valid code pointer, +// NULL is returned. +static address resolve_function_descriptor_to_code_pointer(address p) { + + const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(p); + if (lib) { + // its a real code pointer + return p; + } else { + lib = LoadedLibraries::find_for_data_address(p); + if (lib) { + // pointer to data segment, potential function descriptor + address code_entry = (address)(((FunctionDescriptor*)p)->entry()); + if (LoadedLibraries::find_for_text_address(code_entry)) { + // Its a function descriptor + return code_entry; + } + } + } + return NULL; +} + +bool os::dll_address_to_function_name(address addr, char *buf, + int buflen, int *offset) { + if (offset) { + *offset = -1; + } + if (buf) { + buf[0] = '\0'; + } + + // Resolve function ptr literals first. + addr = resolve_function_descriptor_to_code_pointer(addr); + if (!addr) { + return false; + } + + // Go through Decoder::decode to call getFuncName which reads the name from the traceback table. + return Decoder::decode(addr, buf, buflen, offset); +} + +static int getModuleName(codeptr_t pc, // [in] program counter + char* p_name, size_t namelen, // [out] optional: function name + char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages + ) { + + // initialize output parameters + if (p_name && namelen > 0) { + *p_name = '\0'; + } + if (p_errmsg && errmsglen > 0) { + *p_errmsg = '\0'; + } + + const LoadedLibraryModule* const lib = LoadedLibraries::find_for_text_address((address)pc); + if (lib) { + if (p_name && namelen > 0) { + sprintf(p_name, "%.*s", namelen, lib->get_shortname()); + } + return 0; + } + + if (Verbose) { + fprintf(stderr, "pc outside any module"); + } + + return -1; + +} + +bool os::dll_address_to_library_name(address addr, char* buf, + int buflen, int* offset) { + if (offset) { + *offset = -1; + } + if (buf) { + buf[0] = '\0'; + } + + // Resolve function ptr literals first. + addr = resolve_function_descriptor_to_code_pointer(addr); + if (!addr) { + return false; + } + + if (::getModuleName((codeptr_t) addr, buf, buflen, 0, 0) == 0) { + return true; + } + return false; +} + +// Loads .dll/.so and in case of error it checks if .dll/.so was built +// for the same architecture as Hotspot is running on +void *os::dll_load(const char *filename, char *ebuf, int ebuflen) { + + if (ebuf && ebuflen > 0) { + ebuf[0] = '\0'; + ebuf[ebuflen - 1] = '\0'; + } + + if (!filename || strlen(filename) == 0) { + ::strncpy(ebuf, "dll_load: empty filename specified", ebuflen - 1); + return NULL; + } + + // RTLD_LAZY is currently not implemented. The dl is loaded immediately with all its dependants. + void * result= ::dlopen(filename, RTLD_LAZY); + if (result != NULL) { + // Reload dll cache. Don't do this in signal handling. + LoadedLibraries::reload(); + return result; + } else { + // error analysis when dlopen fails + const char* const error_report = ::dlerror(); + if (error_report && ebuf && ebuflen > 0) { + snprintf(ebuf, ebuflen - 1, "%s, LIBPATH=%s, LD_LIBRARY_PATH=%s : %s", + filename, ::getenv("LIBPATH"), ::getenv("LD_LIBRARY_PATH"), error_report); + } + } + return NULL; +} + +// Glibc-2.0 libdl is not MT safe. If you are building with any glibc, +// chances are you might want to run the generated bits against glibc-2.0 +// libdl.so, so always use locking for any version of glibc. +void* os::dll_lookup(void* handle, const char* name) { + pthread_mutex_lock(&dl_mutex); + void* res = dlsym(handle, name); + pthread_mutex_unlock(&dl_mutex); + return res; +} + +void os::print_dll_info(outputStream *st) { + st->print_cr("Dynamic libraries:"); + LoadedLibraries::print(st); +} + +void os::print_os_info(outputStream* st) { + st->print("OS:"); + + st->print("uname:"); + struct utsname name; + uname(&name); + st->print(name.sysname); st->print(" "); + st->print(name.nodename); st->print(" "); + st->print(name.release); st->print(" "); + st->print(name.version); st->print(" "); + st->print(name.machine); + st->cr(); + + // rlimit + st->print("rlimit:"); + struct rlimit rlim; + + st->print(" STACK "); + getrlimit(RLIMIT_STACK, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + + st->print(", CORE "); + getrlimit(RLIMIT_CORE, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + + st->print(", NPROC "); + st->print("%d", sysconf(_SC_CHILD_MAX)); + + st->print(", NOFILE "); + getrlimit(RLIMIT_NOFILE, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%d", rlim.rlim_cur); + + st->print(", AS "); + getrlimit(RLIMIT_AS, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + + // Print limits on DATA, because it limits the C-heap. + st->print(", DATA "); + getrlimit(RLIMIT_DATA, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + st->cr(); + + // load average + st->print("load average:"); + double loadavg[3] = {-1.L, -1.L, -1.L}; + os::loadavg(loadavg, 3); + st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]); + st->cr(); +} + +void os::print_memory_info(outputStream* st) { + + st->print_cr("Memory:"); + + st->print_cr(" default page size: %s", describe_pagesize(os::vm_page_size())); + st->print_cr(" default stack page size: %s", describe_pagesize(os::vm_page_size())); + st->print_cr(" default shm page size: %s", describe_pagesize(os::Aix::shm_default_page_size())); + st->print_cr(" can use 64K pages dynamically: %s", (os::Aix::can_use_64K_pages() ? "yes" :"no")); + st->print_cr(" can use 16M pages dynamically: %s", (os::Aix::can_use_16M_pages() ? "yes" :"no")); + if (g_multipage_error != 0) { + st->print_cr(" multipage error: %d", g_multipage_error); + } + + // print out LDR_CNTRL because it affects the default page sizes + const char* const ldr_cntrl = ::getenv("LDR_CNTRL"); + st->print_cr(" LDR_CNTRL=%s.", ldr_cntrl ? ldr_cntrl : ""); + + const char* const extshm = ::getenv("EXTSHM"); + st->print_cr(" EXTSHM=%s.", extshm ? extshm : ""); + + // Call os::Aix::get_meminfo() to retrieve memory statistics. + os::Aix::meminfo_t mi; + if (os::Aix::get_meminfo(&mi)) { + char buffer[256]; + if (os::Aix::on_aix()) { + jio_snprintf(buffer, sizeof(buffer), + " physical total : %llu\n" + " physical free : %llu\n" + " swap total : %llu\n" + " swap free : %llu\n", + mi.real_total, + mi.real_free, + mi.pgsp_total, + mi.pgsp_free); + } else { + Unimplemented(); + } + st->print_raw(buffer); + } else { + st->print_cr(" (no more information available)"); + } +} + +void os::pd_print_cpu_info(outputStream* st) { + // cpu + st->print("CPU:"); + st->print("total %d", os::processor_count()); + // It's not safe to query number of active processors after crash + // st->print("(active %d)", os::active_processor_count()); + st->print(" %s", VM_Version::cpu_features()); + st->cr(); +} + +void os::print_siginfo(outputStream* st, void* siginfo) { + // Use common posix version. + os::Posix::print_siginfo_brief(st, (const siginfo_t*) siginfo); + st->cr(); +} + + +static void print_signal_handler(outputStream* st, int sig, + char* buf, size_t buflen); + +void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { + st->print_cr("Signal Handlers:"); + print_signal_handler(st, SIGSEGV, buf, buflen); + print_signal_handler(st, SIGBUS , buf, buflen); + print_signal_handler(st, SIGFPE , buf, buflen); + print_signal_handler(st, SIGPIPE, buf, buflen); + print_signal_handler(st, SIGXFSZ, buf, buflen); + print_signal_handler(st, SIGILL , buf, buflen); + print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); + print_signal_handler(st, SR_signum, buf, buflen); + print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); + print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); + print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); + print_signal_handler(st, BREAK_SIGNAL, buf, buflen); + print_signal_handler(st, SIGTRAP, buf, buflen); + print_signal_handler(st, SIGDANGER, buf, buflen); +} + +static char saved_jvm_path[MAXPATHLEN] = {0}; + +// Find the full path to the current module, libjvm.so or libjvm_g.so +void os::jvm_path(char *buf, jint buflen) { + // Error checking. + if (buflen < MAXPATHLEN) { + assert(false, "must use a large-enough buffer"); + buf[0] = '\0'; + return; + } + // Lazy resolve the path to current module. + if (saved_jvm_path[0] != 0) { + strcpy(buf, saved_jvm_path); + return; + } + + Dl_info dlinfo; + int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); + assert(ret != 0, "cannot locate libjvm"); + char* rp = realpath((char *)dlinfo.dli_fname, buf); + assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?"); + + strcpy(saved_jvm_path, buf); +} + +void os::print_jni_name_prefix_on(outputStream* st, int args_size) { + // no prefix required, not even "_" +} + +void os::print_jni_name_suffix_on(outputStream* st, int args_size) { + // no suffix required +} + +//////////////////////////////////////////////////////////////////////////////// +// sun.misc.Signal support + +static volatile jint sigint_count = 0; + +static void +UserHandler(int sig, void *siginfo, void *context) { + // 4511530 - sem_post is serialized and handled by the manager thread. When + // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We + // don't want to flood the manager thread with sem_post requests. + if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) + return; + + // Ctrl-C is pressed during error reporting, likely because the error + // handler fails to abort. Let VM die immediately. + if (sig == SIGINT && is_error_reported()) { + os::die(); + } + + os::signal_notify(sig); +} + +void* os::user_handler() { + return CAST_FROM_FN_PTR(void*, UserHandler); +} + +extern "C" { + typedef void (*sa_handler_t)(int); + typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +} + +void* os::signal(int signal_number, void* handler) { + struct sigaction sigAct, oldSigAct; + + sigfillset(&(sigAct.sa_mask)); + + // Do not block out synchronous signals in the signal handler. + // Blocking synchronous signals only makes sense if you can really + // be sure that those signals won't happen during signal handling, + // when the blocking applies. Normal signal handlers are lean and + // do not cause signals. But our signal handlers tend to be "risky" + // - secondary SIGSEGV, SIGILL, SIGBUS' may and do happen. + // On AIX, PASE there was a case where a SIGSEGV happened, followed + // by a SIGILL, which was blocked due to the signal mask. The process + // just hung forever. Better to crash from a secondary signal than to hang. + sigdelset(&(sigAct.sa_mask), SIGSEGV); + sigdelset(&(sigAct.sa_mask), SIGBUS); + sigdelset(&(sigAct.sa_mask), SIGILL); + sigdelset(&(sigAct.sa_mask), SIGFPE); + sigdelset(&(sigAct.sa_mask), SIGTRAP); + + sigAct.sa_flags = SA_RESTART|SA_SIGINFO; + + sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler); + + if (sigaction(signal_number, &sigAct, &oldSigAct)) { + // -1 means registration failed + return (void *)-1; + } + + return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler); +} + +void os::signal_raise(int signal_number) { + ::raise(signal_number); +} + +// +// The following code is moved from os.cpp for making this +// code platform specific, which it is by its very nature. +// + +// Will be modified when max signal is changed to be dynamic +int os::sigexitnum_pd() { + return NSIG; +} + +// a counter for each possible signal value +static volatile jint pending_signals[NSIG+1] = { 0 }; + +// Linux(POSIX) specific hand shaking semaphore. +static sem_t sig_sem; + +void os::signal_init_pd() { + // Initialize signal structures + ::memset((void*)pending_signals, 0, sizeof(pending_signals)); + + // Initialize signal semaphore + int rc = ::sem_init(&sig_sem, 0, 0); + guarantee(rc != -1, "sem_init failed"); +} + +void os::signal_notify(int sig) { + Atomic::inc(&pending_signals[sig]); + ::sem_post(&sig_sem); +} + +static int check_pending_signals(bool wait) { + Atomic::store(0, &sigint_count); + for (;;) { + for (int i = 0; i < NSIG + 1; i++) { + jint n = pending_signals[i]; + if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) { + return i; + } + } + if (!wait) { + return -1; + } + JavaThread *thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + bool threadIsSuspended; + do { + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() + + ::sem_wait(&sig_sem); + + // were we externally suspended while we were waiting? + threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); + if (threadIsSuspended) { + // + // The semaphore has been incremented, but while we were waiting + // another thread suspended us. We don't want to continue running + // while suspended because that would surprise the thread that + // suspended us. + // + ::sem_post(&sig_sem); + + thread->java_suspend_self(); + } + } while (threadIsSuspended); + } +} + +int os::signal_lookup() { + return check_pending_signals(false); +} + +int os::signal_wait() { + return check_pending_signals(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// Virtual Memory + +// AddrRange describes an immutable address range +// +// This is a helper class for the 'shared memory bookkeeping' below. +class AddrRange { + friend class ShmBkBlock; + + char* _start; + size_t _size; + +public: + + AddrRange(char* start, size_t size) + : _start(start), _size(size) + {} + + AddrRange(const AddrRange& r) + : _start(r.start()), _size(r.size()) + {} + + char* start() const { return _start; } + size_t size() const { return _size; } + char* end() const { return _start + _size; } + bool is_empty() const { return _size == 0 ? true : false; } + + static AddrRange empty_range() { return AddrRange(NULL, 0); } + + bool contains(const char* p) const { + return start() <= p && end() > p; + } + + bool contains(const AddrRange& range) const { + return start() <= range.start() && end() >= range.end(); + } + + bool intersects(const AddrRange& range) const { + return (range.start() <= start() && range.end() > start()) || + (range.start() < end() && range.end() >= end()) || + contains(range); + } + + bool is_same_range(const AddrRange& range) const { + return start() == range.start() && size() == range.size(); + } + + // return the closest inside range consisting of whole pages + AddrRange find_closest_aligned_range(size_t pagesize) const { + if (pagesize == 0 || is_empty()) { + return empty_range(); + } + char* const from = (char*)align_size_up((intptr_t)_start, pagesize); + char* const to = (char*)align_size_down((intptr_t)end(), pagesize); + if (from > to) { + return empty_range(); + } + return AddrRange(from, to - from); + } +}; + +//////////////////////////////////////////////////////////////////////////// +// shared memory bookkeeping +// +// the os::reserve_memory() API and friends hand out different kind of memory, depending +// on need and circumstances. Memory may be allocated with mmap() or with shmget/shmat. +// +// But these memory types have to be treated differently. For example, to uncommit +// mmap-based memory, msync(MS_INVALIDATE) is needed, to uncommit shmat-based memory, +// disclaim64() is needed. +// +// Therefore we need to keep track of the allocated memory segments and their +// properties. + +// ShmBkBlock: base class for all blocks in the shared memory bookkeeping +class ShmBkBlock { + + ShmBkBlock* _next; + +protected: + + AddrRange _range; + const size_t _pagesize; + const bool _pinned; + +public: + + ShmBkBlock(AddrRange range, size_t pagesize, bool pinned) + : _range(range), _pagesize(pagesize), _pinned(pinned) , _next(NULL) { + + assert(_pagesize == SIZE_4K || _pagesize == SIZE_64K || _pagesize == SIZE_16M, "invalid page size"); + assert(!_range.is_empty(), "invalid range"); + } + + virtual void print(outputStream* st) const { + st->print("0x%p ... 0x%p (%llu) - %d %s pages - %s", + _range.start(), _range.end(), _range.size(), + _range.size() / _pagesize, describe_pagesize(_pagesize), + _pinned ? "pinned" : ""); + } + + enum Type { MMAP, SHMAT }; + virtual Type getType() = 0; + + char* base() const { return _range.start(); } + size_t size() const { return _range.size(); } + + void setAddrRange(AddrRange range) { + _range = range; + } + + bool containsAddress(const char* p) const { + return _range.contains(p); + } + + bool containsRange(const char* p, size_t size) const { + return _range.contains(AddrRange((char*)p, size)); + } + + bool isSameRange(const char* p, size_t size) const { + return _range.is_same_range(AddrRange((char*)p, size)); + } + + virtual bool disclaim(char* p, size_t size) = 0; + virtual bool release() = 0; + + // blocks live in a list. + ShmBkBlock* next() const { return _next; } + void set_next(ShmBkBlock* blk) { _next = blk; } + +}; // end: ShmBkBlock + + +// ShmBkMappedBlock: describes an block allocated with mmap() +class ShmBkMappedBlock : public ShmBkBlock { +public: + + ShmBkMappedBlock(AddrRange range) + : ShmBkBlock(range, SIZE_4K, false) {} // mmap: always 4K, never pinned + + void print(outputStream* st) const { + ShmBkBlock::print(st); + st->print_cr(" - mmap'ed"); + } + + Type getType() { + return MMAP; + } + + bool disclaim(char* p, size_t size) { + + AddrRange r(p, size); + + guarantee(_range.contains(r), "invalid disclaim"); + + // only disclaim whole ranges. + const AddrRange r2 = r.find_closest_aligned_range(_pagesize); + if (r2.is_empty()) { + return true; + } + + const int rc = ::msync(r2.start(), r2.size(), MS_INVALIDATE); + + if (rc != 0) { + warning("msync(0x%p, %llu, MS_INVALIDATE) failed (%d)\n", r2.start(), r2.size(), errno); + } + + return rc == 0 ? true : false; + } + + bool release() { + // mmap'ed blocks are released using munmap + if (::munmap(_range.start(), _range.size()) != 0) { + warning("munmap(0x%p, %llu) failed (%d)\n", _range.start(), _range.size(), errno); + return false; + } + return true; + } +}; // end: ShmBkMappedBlock + +// ShmBkShmatedBlock: describes an block allocated with shmget/shmat() +class ShmBkShmatedBlock : public ShmBkBlock { +public: + + ShmBkShmatedBlock(AddrRange range, size_t pagesize, bool pinned) + : ShmBkBlock(range, pagesize, pinned) {} + + void print(outputStream* st) const { + ShmBkBlock::print(st); + st->print_cr(" - shmat'ed"); + } + + Type getType() { + return SHMAT; + } + + bool disclaim(char* p, size_t size) { + + AddrRange r(p, size); + + if (_pinned) { + return true; + } + + // shmat'ed blocks are disclaimed using disclaim64 + guarantee(_range.contains(r), "invalid disclaim"); + + // only disclaim whole ranges. + const AddrRange r2 = r.find_closest_aligned_range(_pagesize); + if (r2.is_empty()) { + return true; + } + + const bool rc = my_disclaim64(r2.start(), r2.size()); + + if (Verbose && !rc) { + warning("failed to disclaim shm %p-%p\n", r2.start(), r2.end()); + } + + return rc; + } + + bool release() { + bool rc = false; + if (::shmdt(_range.start()) != 0) { + warning("shmdt(0x%p) failed (%d)\n", _range.start(), errno); + } else { + rc = true; + } + return rc; + } + +}; // end: ShmBkShmatedBlock + +static ShmBkBlock* g_shmbk_list = NULL; +static volatile jint g_shmbk_table_lock = 0; + +// keep some usage statistics +static struct { + int nodes; // number of nodes in list + size_t bytes; // reserved - not committed - bytes. + int reserves; // how often reserve was called + int lookups; // how often a lookup was made +} g_shmbk_stats = { 0, 0, 0, 0 }; + +// add information about a shared memory segment to the bookkeeping +static void shmbk_register(ShmBkBlock* p_block) { + guarantee(p_block, "logic error"); + p_block->set_next(g_shmbk_list); + g_shmbk_list = p_block; + g_shmbk_stats.reserves ++; + g_shmbk_stats.bytes += p_block->size(); + g_shmbk_stats.nodes ++; +} + +// remove information about a shared memory segment by its starting address +static void shmbk_unregister(ShmBkBlock* p_block) { + ShmBkBlock* p = g_shmbk_list; + ShmBkBlock* prev = NULL; + while (p) { + if (p == p_block) { + if (prev) { + prev->set_next(p->next()); + } else { + g_shmbk_list = p->next(); + } + g_shmbk_stats.nodes --; + g_shmbk_stats.bytes -= p->size(); + return; + } + prev = p; + p = p->next(); + } + assert(false, "should not happen"); +} + +// given a pointer, return shared memory bookkeeping record for the segment it points into +// using the returned block info must happen under lock protection +static ShmBkBlock* shmbk_find_by_containing_address(const char* addr) { + g_shmbk_stats.lookups ++; + ShmBkBlock* p = g_shmbk_list; + while (p) { + if (p->containsAddress(addr)) { + return p; + } + p = p->next(); + } + return NULL; +} + +// dump all information about all memory segments allocated with os::reserve_memory() +void shmbk_dump_info() { + tty->print_cr("-- shared mem bookkeeping (alive: %d segments, %llu bytes, " + "total reserves: %d total lookups: %d)", + g_shmbk_stats.nodes, g_shmbk_stats.bytes, g_shmbk_stats.reserves, g_shmbk_stats.lookups); + const ShmBkBlock* p = g_shmbk_list; + int i = 0; + while (p) { + p->print(tty); + p = p->next(); + i ++; + } +} + +#define LOCK_SHMBK { ThreadCritical _LOCK_SHMBK; +#define UNLOCK_SHMBK } + +// End: shared memory bookkeeping +//////////////////////////////////////////////////////////////////////////////////////////////////// + +int os::vm_page_size() { + // Seems redundant as all get out + assert(os::Aix::page_size() != -1, "must call os::init"); + return os::Aix::page_size(); +} + +// Aix allocates memory by pages. +int os::vm_allocation_granularity() { + assert(os::Aix::page_size() != -1, "must call os::init"); + return os::Aix::page_size(); +} + +int os::Aix::commit_memory_impl(char* addr, size_t size, bool exec) { + + // Commit is a noop. There is no explicit commit + // needed on AIX. Memory is committed when touched. + // + // Debug : check address range for validity +#ifdef ASSERT + LOCK_SHMBK + ShmBkBlock* const block = shmbk_find_by_containing_address(addr); + if (!block) { + fprintf(stderr, "invalid pointer: " INTPTR_FORMAT "\n", addr); + shmbk_dump_info(); + assert(false, "invalid pointer"); + return false; + } else if (!block->containsRange(addr, size)) { + fprintf(stderr, "invalid range: " INTPTR_FORMAT " .. " INTPTR_FORMAT "\n", addr, addr + size); + shmbk_dump_info(); + assert(false, "invalid range"); + return false; + } + UNLOCK_SHMBK +#endif // ASSERT + + return 0; +} + +bool os::pd_commit_memory(char* addr, size_t size, bool exec) { + return os::Aix::commit_memory_impl(addr, size, exec) == 0; +} + +void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec, + const char* mesg) { + assert(mesg != NULL, "mesg must be specified"); + os::Aix::commit_memory_impl(addr, size, exec); +} + +int os::Aix::commit_memory_impl(char* addr, size_t size, + size_t alignment_hint, bool exec) { + return os::Aix::commit_memory_impl(addr, size, exec); +} + +bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { + return os::Aix::commit_memory_impl(addr, size, alignment_hint, exec) == 0; +} + +void os::pd_commit_memory_or_exit(char* addr, size_t size, + size_t alignment_hint, bool exec, + const char* mesg) { + os::Aix::commit_memory_impl(addr, size, alignment_hint, exec); +} + +bool os::pd_uncommit_memory(char* addr, size_t size) { + + // Delegate to ShmBkBlock class which knows how to uncommit its memory. + + bool rc = false; + LOCK_SHMBK + ShmBkBlock* const block = shmbk_find_by_containing_address(addr); + if (!block) { + fprintf(stderr, "invalid pointer: 0x%p.\n", addr); + shmbk_dump_info(); + assert(false, "invalid pointer"); + return false; + } else if (!block->containsRange(addr, size)) { + fprintf(stderr, "invalid range: 0x%p .. 0x%p.\n", addr, addr + size); + shmbk_dump_info(); + assert(false, "invalid range"); + return false; + } + rc = block->disclaim(addr, size); + UNLOCK_SHMBK + + if (Verbose && !rc) { + warning("failed to disclaim 0x%p .. 0x%p (0x%llX bytes).", addr, addr + size, size); + } + return rc; +} + +bool os::pd_create_stack_guard_pages(char* addr, size_t size) { + return os::guard_memory(addr, size); +} + +bool os::remove_stack_guard_pages(char* addr, size_t size) { + return os::unguard_memory(addr, size); +} + +void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { +} + +void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { +} + +void os::numa_make_global(char *addr, size_t bytes) { +} + +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { +} + +bool os::numa_topology_changed() { + return false; +} + +size_t os::numa_get_groups_num() { + return 1; +} + +int os::numa_get_group_id() { + return 0; +} + +size_t os::numa_get_leaf_groups(int *ids, size_t size) { + if (size > 0) { + ids[0] = 0; + return 1; + } + return 0; +} + +bool os::get_page_info(char *start, page_info* info) { + return false; +} + +char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { + return end; +} + +// Flags for reserve_shmatted_memory: +#define RESSHM_WISHADDR_OR_FAIL 1 +#define RESSHM_TRY_16M_PAGES 2 +#define RESSHM_16M_PAGES_OR_FAIL 4 + +// Result of reserve_shmatted_memory: +struct shmatted_memory_info_t { + char* addr; + size_t pagesize; + bool pinned; +}; + +// Reserve a section of shmatted memory. +// params: +// bytes [in]: size of memory, in bytes +// requested_addr [in]: wish address. +// NULL = no wish. +// If RESSHM_WISHADDR_OR_FAIL is set in flags and wish address cannot +// be obtained, function will fail. Otherwise wish address is treated as hint and +// another pointer is returned. +// flags [in]: some flags. Valid flags are: +// RESSHM_WISHADDR_OR_FAIL - fail if wish address is given and cannot be obtained. +// RESSHM_TRY_16M_PAGES - try to allocate from 16M page pool +// (requires UseLargePages and Use16MPages) +// RESSHM_16M_PAGES_OR_FAIL - if you cannot allocate from 16M page pool, fail. +// Otherwise any other page size will do. +// p_info [out] : holds information about the created shared memory segment. +static bool reserve_shmatted_memory(size_t bytes, char* requested_addr, int flags, shmatted_memory_info_t* p_info) { + + assert(p_info, "parameter error"); + + // init output struct. + p_info->addr = NULL; + + // neither should we be here for EXTSHM=ON. + if (os::Aix::extshm()) { + ShouldNotReachHere(); + } + + // extract flags. sanity checks. + const bool wishaddr_or_fail = + flags & RESSHM_WISHADDR_OR_FAIL; + const bool try_16M_pages = + flags & RESSHM_TRY_16M_PAGES; + const bool f16M_pages_or_fail = + flags & RESSHM_16M_PAGES_OR_FAIL; + + // first check: if a wish address is given and it is mandatory, but not aligned to segment boundary, + // shmat will fail anyway, so save some cycles by failing right away + if (requested_addr && ((uintptr_t)requested_addr % SIZE_256M == 0)) { + if (wishaddr_or_fail) { + return false; + } else { + requested_addr = NULL; + } + } + + char* addr = NULL; + + // Align size of shm up to the largest possible page size, to avoid errors later on when we try to change + // pagesize dynamically. + const size_t size = align_size_up(bytes, SIZE_16M); + + // reserve the shared segment + int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRUSR | S_IWUSR); + if (shmid == -1) { + warning("shmget(.., %lld, ..) failed (errno: %d).", size, errno); + return false; + } + + // Important note: + // It is very important that we, upon leaving this function, do not leave a shm segment alive. + // We must right after attaching it remove it from the system. System V shm segments are global and + // survive the process. + // So, from here on: Do not assert. Do not return. Always do a "goto cleanup_shm". + + // try forcing the page size + size_t pagesize = -1; // unknown so far + + if (UseLargePages) { + + struct shmid_ds shmbuf; + memset(&shmbuf, 0, sizeof(shmbuf)); + + // First, try to take from 16M page pool if... + if (os::Aix::can_use_16M_pages() // we can ... + && Use16MPages // we are not explicitly forbidden to do so (-XX:-Use16MPages).. + && try_16M_pages) { // caller wants us to. + shmbuf.shm_pagesize = SIZE_16M; + if (shmctl(shmid, SHM_PAGESIZE, &shmbuf) == 0) { + pagesize = SIZE_16M; + } else { + warning("Failed to allocate %d 16M pages. 16M page pool might be exhausted. (shmctl failed with %d)", + size / SIZE_16M, errno); + if (f16M_pages_or_fail) { + goto cleanup_shm; + } + } + } + + // Nothing yet? Try setting 64K pages. Note that I never saw this fail, but in theory it might, + // because the 64K page pool may also be exhausted. + if (pagesize == -1) { + shmbuf.shm_pagesize = SIZE_64K; + if (shmctl(shmid, SHM_PAGESIZE, &shmbuf) == 0) { + pagesize = SIZE_64K; + } else { + warning("Failed to allocate %d 64K pages. (shmctl failed with %d)", + size / SIZE_64K, errno); + // here I give up. leave page_size -1 - later, after attaching, we will query the + // real page size of the attached memory. (in theory, it may be something different + // from 4K if LDR_CNTRL SHM_PSIZE is set) + } + } + } + + // sanity point + assert(pagesize == -1 || pagesize == SIZE_16M || pagesize == SIZE_64K, "wrong page size"); + + // Now attach the shared segment. + addr = (char*) shmat(shmid, requested_addr, 0); + if (addr == (char*)-1) { + // How to handle attach failure: + // If it failed for a specific wish address, tolerate this: in that case, if wish address was + // mandatory, fail, if not, retry anywhere. + // If it failed for any other reason, treat that as fatal error. + addr = NULL; + if (requested_addr) { + if (wishaddr_or_fail) { + goto cleanup_shm; + } else { + addr = (char*) shmat(shmid, NULL, 0); + if (addr == (char*)-1) { // fatal + addr = NULL; + warning("shmat failed (errno: %d)", errno); + goto cleanup_shm; + } + } + } else { // fatal + addr = NULL; + warning("shmat failed (errno: %d)", errno); + goto cleanup_shm; + } + } + + // sanity point + assert(addr && addr != (char*) -1, "wrong address"); + + // after successful Attach remove the segment - right away. + if (::shmctl(shmid, IPC_RMID, NULL) == -1) { + warning("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno); + guarantee(false, "failed to remove shared memory segment!"); + } + shmid = -1; + + // query the real page size. In case setting the page size did not work (see above), the system + // may have given us something other then 4K (LDR_CNTRL) + { + const size_t real_pagesize = os::Aix::query_pagesize(addr); + if (pagesize != -1) { + assert(pagesize == real_pagesize, "unexpected pagesize after shmat"); + } else { + pagesize = real_pagesize; + } + } + + // Now register the reserved block with internal book keeping. + LOCK_SHMBK + const bool pinned = pagesize >= SIZE_16M ? true : false; + ShmBkShmatedBlock* const p_block = new ShmBkShmatedBlock(AddrRange(addr, size), pagesize, pinned); + assert(p_block, ""); + shmbk_register(p_block); + UNLOCK_SHMBK + +cleanup_shm: + + // if we have not done so yet, remove the shared memory segment. This is very important. + if (shmid != -1) { + if (::shmctl(shmid, IPC_RMID, NULL) == -1) { + warning("shmctl(%u, IPC_RMID) failed (%d)\n", shmid, errno); + guarantee(false, "failed to remove shared memory segment!"); + } + shmid = -1; + } + + // trace + if (Verbose && !addr) { + if (requested_addr != NULL) { + warning("failed to shm-allocate 0x%llX bytes at with address 0x%p.", size, requested_addr); + } else { + warning("failed to shm-allocate 0x%llX bytes at any address.", size); + } + } + + // hand info to caller + if (addr) { + p_info->addr = addr; + p_info->pagesize = pagesize; + p_info->pinned = pagesize == SIZE_16M ? true : false; + } + + // sanity test: + if (requested_addr && addr && wishaddr_or_fail) { + guarantee(addr == requested_addr, "shmat error"); + } + + // just one more test to really make sure we have no dangling shm segments. + guarantee(shmid == -1, "dangling shm segments"); + + return addr ? true : false; + +} // end: reserve_shmatted_memory + +// Reserve memory using mmap. Behaves the same as reserve_shmatted_memory(): +// will return NULL in case of an error. +static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) { + + // if a wish address is given, but not aligned to 4K page boundary, mmap will fail. + if (requested_addr && ((uintptr_t)requested_addr % os::vm_page_size() != 0)) { + warning("Wish address 0x%p not aligned to page boundary.", requested_addr); + return NULL; + } + + const size_t size = align_size_up(bytes, SIZE_4K); + + // Note: MAP_SHARED (instead of MAP_PRIVATE) needed to be able to + // msync(MS_INVALIDATE) (see os::uncommit_memory) + int flags = MAP_ANONYMOUS | MAP_SHARED; + + // MAP_FIXED is needed to enforce requested_addr - manpage is vague about what + // it means if wishaddress is given but MAP_FIXED is not set. + // + // Note however that this changes semantics in SPEC1170 mode insofar as MAP_FIXED + // clobbers the address range, which is probably not what the caller wants. That's + // why I assert here (again) that the SPEC1170 compat mode is off. + // If we want to be able to run under SPEC1170, we have to do some porting and + // testing. + if (requested_addr != NULL) { + assert(!os::Aix::xpg_sus_mode(), "SPEC1170 mode not allowed."); + flags |= MAP_FIXED; + } + + char* addr = (char*)::mmap(requested_addr, size, PROT_READ|PROT_WRITE|PROT_EXEC, flags, -1, 0); + + if (addr == MAP_FAILED) { + // attach failed: tolerate for specific wish addresses. Not being able to attach + // anywhere is a fatal error. + if (requested_addr == NULL) { + // It's ok to fail here if the machine has not enough memory. + warning("mmap(NULL, 0x%llX, ..) failed (%d)", size, errno); + } + addr = NULL; + goto cleanup_mmap; + } + + // If we did request a specific address and that address was not available, fail. + if (addr && requested_addr) { + guarantee(addr == requested_addr, "unexpected"); + } + + // register this mmap'ed segment with book keeping + LOCK_SHMBK + ShmBkMappedBlock* const p_block = new ShmBkMappedBlock(AddrRange(addr, size)); + assert(p_block, ""); + shmbk_register(p_block); + UNLOCK_SHMBK + +cleanup_mmap: + + if (addr) { + if (Verbose) { + fprintf(stderr, "mmap-allocated 0x%p .. 0x%p (0x%llX bytes)\n", addr, addr + bytes, bytes); + } + } + else { + if (requested_addr != NULL) { + warning("failed to mmap-allocate 0x%llX bytes at wish address 0x%p.", bytes, requested_addr); + } else { + warning("failed to mmap-allocate 0x%llX bytes at any address.", bytes); + } + } + + return addr; + +} // end: reserve_mmaped_memory + +// Reserves and attaches a shared memory segment. +// Will assert if a wish address is given and could not be obtained. +char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) { + return os::attempt_reserve_memory_at(bytes, requested_addr); +} + +bool os::pd_release_memory(char* addr, size_t size) { + + // delegate to ShmBkBlock class which knows how to uncommit its memory. + + bool rc = false; + LOCK_SHMBK + ShmBkBlock* const block = shmbk_find_by_containing_address(addr); + if (!block) { + fprintf(stderr, "invalid pointer: 0x%p.\n", addr); + shmbk_dump_info(); + assert(false, "invalid pointer"); + return false; + } + else if (!block->isSameRange(addr, size)) { + if (block->getType() == ShmBkBlock::MMAP) { + // Release only the same range or a the beginning or the end of a range. + if (block->base() == addr && size < block->size()) { + ShmBkMappedBlock* const b = new ShmBkMappedBlock(AddrRange(block->base() + size, block->size() - size)); + assert(b, ""); + shmbk_register(b); + block->setAddrRange(AddrRange(addr, size)); + } + else if (addr > block->base() && addr + size == block->base() + block->size()) { + ShmBkMappedBlock* const b = new ShmBkMappedBlock(AddrRange(block->base(), block->size() - size)); + assert(b, ""); + shmbk_register(b); + block->setAddrRange(AddrRange(addr, size)); + } + else { + fprintf(stderr, "invalid mmap range: 0x%p .. 0x%p.\n", addr, addr + size); + shmbk_dump_info(); + assert(false, "invalid mmap range"); + return false; + } + } + else { + // Release only the same range. No partial release allowed. + // Soften the requirement a bit, because the user may think he owns a smaller size + // than the block is due to alignment etc. + if (block->base() != addr || block->size() < size) { + fprintf(stderr, "invalid shmget range: 0x%p .. 0x%p.\n", addr, addr + size); + shmbk_dump_info(); + assert(false, "invalid shmget range"); + return false; + } + } + } + rc = block->release(); + assert(rc, "release failed"); + // remove block from bookkeeping + shmbk_unregister(block); + delete block; + UNLOCK_SHMBK + + if (!rc) { + warning("failed to released %lu bytes at 0x%p", size, addr); + } + + return rc; +} + +static bool checked_mprotect(char* addr, size_t size, int prot) { + + // Little problem here: if SPEC1170 behaviour is off, mprotect() on AIX will + // not tell me if protection failed when trying to protect an un-protectable range. + // + // This means if the memory was allocated using shmget/shmat, protection wont work + // but mprotect will still return 0: + // + // See http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/mprotect.htm + + bool rc = ::mprotect(addr, size, prot) == 0 ? true : false; + + if (!rc) { + const char* const s_errno = strerror(errno); + warning("mprotect(" PTR_FORMAT "-" PTR_FORMAT ", 0x%X) failed (%s).", addr, addr + size, prot, s_errno); + return false; + } + + // mprotect success check + // + // Mprotect said it changed the protection but can I believe it? + // + // To be sure I need to check the protection afterwards. Try to + // read from protected memory and check whether that causes a segfault. + // + if (!os::Aix::xpg_sus_mode()) { + + if (StubRoutines::SafeFetch32_stub()) { + + const bool read_protected = + (SafeFetch32((int*)addr, 0x12345678) == 0x12345678 && + SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false; + + if (prot & PROT_READ) { + rc = !read_protected; + } else { + rc = read_protected; + } + } + } + if (!rc) { + assert(false, "mprotect failed."); + } + return rc; +} + +// Set protections specified +bool os::protect_memory(char* addr, size_t size, ProtType prot, bool is_committed) { + unsigned int p = 0; + switch (prot) { + case MEM_PROT_NONE: p = PROT_NONE; break; + case MEM_PROT_READ: p = PROT_READ; break; + case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break; + case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break; + default: + ShouldNotReachHere(); + } + // is_committed is unused. + return checked_mprotect(addr, size, p); +} + +bool os::guard_memory(char* addr, size_t size) { + return checked_mprotect(addr, size, PROT_NONE); +} + +bool os::unguard_memory(char* addr, size_t size) { + return checked_mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC); +} + +// Large page support + +static size_t _large_page_size = 0; + +// Enable large page support if OS allows that. +void os::large_page_init() { + + // Note: os::Aix::query_multipage_support must run first. + + if (!UseLargePages) { + return; + } + + if (!Aix::can_use_64K_pages()) { + assert(!Aix::can_use_16M_pages(), "64K is a precondition for 16M."); + UseLargePages = false; + return; + } + + if (!Aix::can_use_16M_pages() && Use16MPages) { + fprintf(stderr, "Cannot use 16M pages. Please ensure that there is a 16M page pool " + " and that the VM runs with CAP_BYPASS_RAC_VMM and CAP_PROPAGATE capabilities.\n"); + } + + // Do not report 16M page alignment as part of os::_page_sizes if we are + // explicitly forbidden from using 16M pages. Doing so would increase the + // alignment the garbage collector calculates with, slightly increasing + // heap usage. We should only pay for 16M alignment if we really want to + // use 16M pages. + if (Use16MPages && Aix::can_use_16M_pages()) { + _large_page_size = SIZE_16M; + _page_sizes[0] = SIZE_16M; + _page_sizes[1] = SIZE_64K; + _page_sizes[2] = SIZE_4K; + _page_sizes[3] = 0; + } else if (Aix::can_use_64K_pages()) { + _large_page_size = SIZE_64K; + _page_sizes[0] = SIZE_64K; + _page_sizes[1] = SIZE_4K; + _page_sizes[2] = 0; + } + + if (Verbose) { + ("Default large page size is 0x%llX.", _large_page_size); + } +} // end: os::large_page_init() + +char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. + Unimplemented(); + return 0; +} + +bool os::release_memory_special(char* base, size_t bytes) { + // detaching the SHM segment will also delete it, see reserve_memory_special() + Unimplemented(); + return false; +} + +size_t os::large_page_size() { + return _large_page_size; +} + +bool os::can_commit_large_page_memory() { + // Well, sadly we cannot commit anything at all (see comment in + // os::commit_memory) but we claim to so we can make use of large pages + return true; +} + +bool os::can_execute_large_page_memory() { + // We can do that + return true; +} + +// Reserve memory at an arbitrary address, only if that area is +// available (and not reserved for something else). +char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { + + bool use_mmap = false; + + // mmap: smaller graining, no large page support + // shm: large graining (256M), large page support, limited number of shm segments + // + // Prefer mmap wherever we either do not need large page support or have OS limits + + if (!UseLargePages || bytes < SIZE_16M) { + use_mmap = true; + } + + char* addr = NULL; + if (use_mmap) { + addr = reserve_mmaped_memory(bytes, requested_addr); + } else { + // shmat: wish address is mandatory, and do not try 16M pages here. + shmatted_memory_info_t info; + const int flags = RESSHM_WISHADDR_OR_FAIL; + if (reserve_shmatted_memory(bytes, requested_addr, flags, &info)) { + addr = info.addr; + } + } + + return addr; +} + +size_t os::read(int fd, void *buf, unsigned int nBytes) { + return ::read(fd, buf, nBytes); +} + +#define NANOSECS_PER_MILLISEC 1000000 + +int os::sleep(Thread* thread, jlong millis, bool interruptible) { + assert(thread == Thread::current(), "thread consistency check"); + + // Prevent nasty overflow in deadline calculation + // by handling long sleeps similar to solaris or windows. + const jlong limit = INT_MAX; + int result; + while (millis > limit) { + if ((result = os::sleep(thread, limit, interruptible)) != OS_OK) { + return result; + } + millis -= limit; + } + + ParkEvent * const slp = thread->_SleepEvent; + slp->reset(); + OrderAccess::fence(); + + if (interruptible) { + jlong prevtime = javaTimeNanos(); + + // Prevent precision loss and too long sleeps + jlong deadline = prevtime + millis * NANOSECS_PER_MILLISEC; + + for (;;) { + if (os::is_interrupted(thread, true)) { + return OS_INTRPT; + } + + jlong newtime = javaTimeNanos(); + + assert(newtime >= prevtime, "time moving backwards"); + // Doing prevtime and newtime in microseconds doesn't help precision, + // and trying to round up to avoid lost milliseconds can result in a + // too-short delay. + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + + if (millis <= 0) { + return OS_OK; + } + + // Stop sleeping if we passed the deadline + if (newtime >= deadline) { + return OS_OK; + } + + prevtime = newtime; + + { + assert(thread->is_Java_thread(), "sanity check"); + JavaThread *jt = (JavaThread *) thread; + ThreadBlockInVM tbivm(jt); + OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); + + jt->set_suspend_equivalent(); + + slp->park(millis); + + // were we externally suspended while we were waiting? + jt->check_and_wait_while_suspended(); + } + } + } else { + OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + jlong prevtime = javaTimeNanos(); + + // Prevent precision loss and too long sleeps + jlong deadline = prevtime + millis * NANOSECS_PER_MILLISEC; + + for (;;) { + // It'd be nice to avoid the back-to-back javaTimeNanos() calls on + // the 1st iteration ... + jlong newtime = javaTimeNanos(); + + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + // - HS14 Commented out as not implemented. + // - TODO Maybe we should implement it? + //assert(!Aix::supports_monotonic_clock(), "time moving backwards"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + } + + if (millis <= 0) break; + + if (newtime >= deadline) { + break; + } + + prevtime = newtime; + slp->park(millis); + } + return OS_OK; + } +} + +int os::naked_sleep() { + // %% make the sleep time an integer flag. for now use 1 millisec. + return os::sleep(Thread::current(), 1, false); +} + +// Sleep forever; naked call to OS-specific sleep; use with CAUTION +void os::infinite_sleep() { + while (true) { // sleep forever ... + ::sleep(100); // ... 100 seconds at a time + } +} + +// Used to convert frequent JVM_Yield() to nops +bool os::dont_yield() { + return DontYieldALot; +} + +void os::yield() { + sched_yield(); +} + +os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN; } + +void os::yield_all(int attempts) { + // Yields to all threads, including threads with lower priorities + // Threads on Linux are all with same priority. The Solaris style + // os::yield_all() with nanosleep(1ms) is not necessary. + sched_yield(); +} + +// Called from the tight loops to possibly influence time-sharing heuristics +void os::loop_breaker(int attempts) { + os::yield_all(attempts); +} + +//////////////////////////////////////////////////////////////////////////////// +// thread priority support + +// From AIX manpage to pthread_setschedparam +// (see: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp? +// topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_setschedparam.htm): +// +// "If schedpolicy is SCHED_OTHER, then sched_priority must be in the +// range from 40 to 80, where 40 is the least favored priority and 80 +// is the most favored." +// +// (Actually, I doubt this even has an impact on AIX, as we do kernel +// scheduling there; however, this still leaves iSeries.) +// +// We use the same values for AIX and PASE. +int os::java_to_os_priority[CriticalPriority + 1] = { + 54, // 0 Entry should never be used + + 55, // 1 MinPriority + 55, // 2 + 56, // 3 + + 56, // 4 + 57, // 5 NormPriority + 57, // 6 + + 58, // 7 + 58, // 8 + 59, // 9 NearMaxPriority + + 60, // 10 MaxPriority + + 60 // 11 CriticalPriority +}; + +OSReturn os::set_native_priority(Thread* thread, int newpri) { + if (!UseThreadPriorities) return OS_OK; + pthread_t thr = thread->osthread()->pthread_id(); + int policy = SCHED_OTHER; + struct sched_param param; + param.sched_priority = newpri; + int ret = pthread_setschedparam(thr, policy, ¶m); + + if (Verbose) { + if (ret == 0) { + fprintf(stderr, "changed priority of thread %d to %d\n", (int)thr, newpri); + } else { + fprintf(stderr, "Could not changed priority for thread %d to %d (error %d, %s)\n", + (int)thr, newpri, ret, strerror(ret)); + } + } + return (ret == 0) ? OS_OK : OS_ERR; +} + +OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) { + if (!UseThreadPriorities) { + *priority_ptr = java_to_os_priority[NormPriority]; + return OS_OK; + } + pthread_t thr = thread->osthread()->pthread_id(); + int policy = SCHED_OTHER; + struct sched_param param; + int ret = pthread_getschedparam(thr, &policy, ¶m); + *priority_ptr = param.sched_priority; + + return (ret == 0) ? OS_OK : OS_ERR; +} + +// Hint to the underlying OS that a task switch would not be good. +// Void return because it's a hint and can fail. +void os::hint_no_preempt() {} + +//////////////////////////////////////////////////////////////////////////////// +// suspend/resume support + +// the low-level signal-based suspend/resume support is a remnant from the +// old VM-suspension that used to be for java-suspension, safepoints etc, +// within hotspot. Now there is a single use-case for this: +// - calling get_thread_pc() on the VMThread by the flat-profiler task +// that runs in the watcher thread. +// The remaining code is greatly simplified from the more general suspension +// code that used to be used. +// +// The protocol is quite simple: +// - suspend: +// - sends a signal to the target thread +// - polls the suspend state of the osthread using a yield loop +// - target thread signal handler (SR_handler) sets suspend state +// and blocks in sigsuspend until continued +// - resume: +// - sets target osthread state to continue +// - sends signal to end the sigsuspend loop in the SR_handler +// +// Note that the SR_lock plays no role in this suspend/resume protocol. +// + +static void resume_clear_context(OSThread *osthread) { + osthread->set_ucontext(NULL); + osthread->set_siginfo(NULL); +} + +static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { + osthread->set_ucontext(context); + osthread->set_siginfo(siginfo); +} + +// +// Handler function invoked when a thread's execution is suspended or +// resumed. We have to be careful that only async-safe functions are +// called here (Note: most pthread functions are not async safe and +// should be avoided.) +// +// Note: sigwait() is a more natural fit than sigsuspend() from an +// interface point of view, but sigwait() prevents the signal hander +// from being run. libpthread would get very confused by not having +// its signal handlers run and prevents sigwait()'s use with the +// mutex granting granting signal. +// +// Currently only ever called on the VMThread and JavaThreads (PC sampling). +// +static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { + // Save and restore errno to avoid confusing native code with EINTR + // after sigsuspend. + int old_errno = errno; + + Thread* thread = Thread::current(); + OSThread* osthread = thread->osthread(); + assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); + + os::SuspendResume::State current = osthread->sr.state(); + if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { + suspend_save_context(osthread, siginfo, context); + + // attempt to switch the state, we assume we had a SUSPEND_REQUEST + os::SuspendResume::State state = osthread->sr.suspended(); + if (state == os::SuspendResume::SR_SUSPENDED) { + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, SR_signum); + + // wait here until we are resumed + while (1) { + sigsuspend(&suspend_set); + + os::SuspendResume::State result = osthread->sr.running(); + if (result == os::SuspendResume::SR_RUNNING) { + break; + } + } + + } else if (state == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else { + ShouldNotReachHere(); + } + + resume_clear_context(osthread); + } else if (current == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { + // ignore + } else { + ShouldNotReachHere(); + } + + errno = old_errno; +} + + +static int SR_initialize() { + struct sigaction act; + char *s; + // Get signal number to use for suspend/resume + if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) { + int sig = ::strtol(s, 0, 10); + if (sig > 0 || sig < NSIG) { + SR_signum = sig; + } + } + + assert(SR_signum > SIGSEGV && SR_signum > SIGBUS, + "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769"); + + sigemptyset(&SR_sigset); + sigaddset(&SR_sigset, SR_signum); + + // Set up signal handler for suspend/resume. + act.sa_flags = SA_RESTART|SA_SIGINFO; + act.sa_handler = (void (*)(int)) SR_handler; + + // SR_signum is blocked by default. + // 4528190 - We also need to block pthread restart signal (32 on all + // supported Linux platforms). Note that LinuxThreads need to block + // this signal for all threads to work properly. So we don't have + // to use hard-coded signal number when setting up the mask. + pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask); + + if (sigaction(SR_signum, &act, 0) == -1) { + return -1; + } + + // Save signal flag + os::Aix::set_our_sigflags(SR_signum, act.sa_flags); + return 0; +} + +static int SR_finalize() { + return 0; +} + +static int sr_notify(OSThread* osthread) { + int status = pthread_kill(osthread->pthread_id(), SR_signum); + assert_status(status == 0, status, "pthread_kill"); + return status; +} + +// "Randomly" selected value for how long we want to spin +// before bailing out on suspending a thread, also how often +// we send a signal to a thread we want to resume +static const int RANDOMLY_LARGE_INTEGER = 1000000; +static const int RANDOMLY_LARGE_INTEGER2 = 100; + +// returns true on success and false on error - really an error is fatal +// but this seems the normal response to library errors +static bool do_suspend(OSThread* osthread) { + assert(osthread->sr.is_running(), "thread should be running"); + // mark as suspended and send signal + + if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { + // failed to switch, state wasn't running? + ShouldNotReachHere(); + return false; + } + + if (sr_notify(osthread) != 0) { + // try to cancel, switch to running + + os::SuspendResume::State result = osthread->sr.cancel_suspend(); + if (result == os::SuspendResume::SR_RUNNING) { + // cancelled + return false; + } else if (result == os::SuspendResume::SR_SUSPENDED) { + // somehow managed to suspend + return true; + } else { + ShouldNotReachHere(); + return false; + } + } + + // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED + + for (int n = 0; !osthread->sr.is_suspended(); n++) { + for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) { + os::yield_all(i); + } + + // timeout, try to cancel the request + if (n >= RANDOMLY_LARGE_INTEGER) { + os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); + if (cancelled == os::SuspendResume::SR_RUNNING) { + return false; + } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { + return true; + } else { + ShouldNotReachHere(); + return false; + } + } + } + + guarantee(osthread->sr.is_suspended(), "Must be suspended"); + return true; +} + +static void do_resume(OSThread* osthread) { + //assert(osthread->sr.is_suspended(), "thread should be suspended"); + + if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { + // failed to switch to WAKEUP_REQUEST + ShouldNotReachHere(); + return; + } + + while (!osthread->sr.is_running()) { + if (sr_notify(osthread) == 0) { + for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) { + for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) { + os::yield_all(i); + } + } + } else { + ShouldNotReachHere(); + } + } + + guarantee(osthread->sr.is_running(), "Must be running!"); +} + +//////////////////////////////////////////////////////////////////////////////// +// interrupt support + +void os::interrupt(Thread* thread) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + if (!osthread->interrupted()) { + osthread->set_interrupted(true); + // More than one thread can get here with the same value of osthread, + // resulting in multiple notifications. We do, however, want the store + // to interrupted() to be visible to other threads before we execute unpark(). + OrderAccess::fence(); + ParkEvent * const slp = thread->_SleepEvent; + if (slp != NULL) slp->unpark(); + } + + // For JSR166. Unpark even if interrupt status already was set + if (thread->is_Java_thread()) + ((JavaThread*)thread)->parker()->unpark(); + + ParkEvent * ev = thread->_ParkEvent; + if (ev != NULL) ev->unpark(); + +} + +bool os::is_interrupted(Thread* thread, bool clear_interrupted) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + bool interrupted = osthread->interrupted(); + + if (interrupted && clear_interrupted) { + osthread->set_interrupted(false); + // consider thread->_SleepEvent->reset() ... optional optimization + } + + return interrupted; +} + +/////////////////////////////////////////////////////////////////////////////////// +// signal handling (except suspend/resume) + +// This routine may be used by user applications as a "hook" to catch signals. +// The user-defined signal handler must pass unrecognized signals to this +// routine, and if it returns true (non-zero), then the signal handler must +// return immediately. If the flag "abort_if_unrecognized" is true, then this +// routine will never retun false (zero), but instead will execute a VM panic +// routine kill the process. +// +// If this routine returns false, it is OK to call it again. This allows +// the user-defined signal handler to perform checks either before or after +// the VM performs its own checks. Naturally, the user code would be making +// a serious error if it tried to handle an exception (such as a null check +// or breakpoint) that the VM was generating for its own correct operation. +// +// This routine may recognize any of the following kinds of signals: +// SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1. +// It should be consulted by handlers for any of those signals. +// +// The caller of this routine must pass in the three arguments supplied +// to the function referred to in the "sa_sigaction" (not the "sa_handler") +// field of the structure passed to sigaction(). This routine assumes that +// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART. +// +// Note that the VM will print warnings if it detects conflicting signal +// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers". +// +extern "C" JNIEXPORT int +JVM_handle_aix_signal(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized); + +// Set thread signal mask (for some reason on AIX sigthreadmask() seems +// to be the thing to call; documentation is not terribly clear about whether +// pthread_sigmask also works, and if it does, whether it does the same. +bool set_thread_signal_mask(int how, const sigset_t* set, sigset_t* oset) { + const int rc = ::pthread_sigmask(how, set, oset); + // return value semantics differ slightly for error case: + // pthread_sigmask returns error number, sigthreadmask -1 and sets global errno + // (so, pthread_sigmask is more theadsafe for error handling) + // But success is always 0. + return rc == 0 ? true : false; +} + +// Function to unblock all signals which are, according +// to POSIX, typical program error signals. If they happen while being blocked, +// they typically will bring down the process immediately. +bool unblock_program_error_signals() { + sigset_t set; + ::sigemptyset(&set); + ::sigaddset(&set, SIGILL); + ::sigaddset(&set, SIGBUS); + ::sigaddset(&set, SIGFPE); + ::sigaddset(&set, SIGSEGV); + return set_thread_signal_mask(SIG_UNBLOCK, &set, NULL); +} + +// Renamed from 'signalHandler' to avoid collision with other shared libs. +void javaSignalHandler(int sig, siginfo_t* info, void* uc) { + assert(info != NULL && uc != NULL, "it must be old kernel"); + + // Never leave program error signals blocked; + // on all our platforms they would bring down the process immediately when + // getting raised while being blocked. + unblock_program_error_signals(); + + JVM_handle_aix_signal(sig, info, uc, true); +} + + +// This boolean allows users to forward their own non-matching signals +// to JVM_handle_aix_signal, harmlessly. +bool os::Aix::signal_handlers_are_installed = false; + +// For signal-chaining +struct sigaction os::Aix::sigact[MAXSIGNUM]; +unsigned int os::Aix::sigs = 0; +bool os::Aix::libjsig_is_loaded = false; +typedef struct sigaction *(*get_signal_t)(int); +get_signal_t os::Aix::get_signal_action = NULL; + +struct sigaction* os::Aix::get_chained_signal_action(int sig) { + struct sigaction *actp = NULL; + + if (libjsig_is_loaded) { + // Retrieve the old signal handler from libjsig + actp = (*get_signal_action)(sig); + } + if (actp == NULL) { + // Retrieve the preinstalled signal handler from jvm + actp = get_preinstalled_handler(sig); + } + + return actp; +} + +static bool call_chained_handler(struct sigaction *actp, int sig, + siginfo_t *siginfo, void *context) { + Unimplemented(); + return true; +} + +bool os::Aix::chained_handler(int sig, siginfo_t* siginfo, void* context) { + bool chained = false; + // signal-chaining + if (UseSignalChaining) { + struct sigaction *actp = get_chained_signal_action(sig); + if (actp != NULL) { + chained = call_chained_handler(actp, sig, siginfo, context); + } + } + return chained; +} + +struct sigaction* os::Aix::get_preinstalled_handler(int sig) { + if ((((unsigned int)1 << sig) & sigs) != 0) { + return &sigact[sig]; + } + return NULL; +} + +void os::Aix::save_preinstalled_handler(int sig, struct sigaction& oldAct) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigact[sig] = oldAct; + sigs |= (unsigned int)1 << sig; +} + +// for diagnostic +int os::Aix::sigflags[MAXSIGNUM]; + +int os::Aix::get_our_sigflags(int sig) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + return sigflags[sig]; +} + +void os::Aix::set_our_sigflags(int sig, int flags) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigflags[sig] = flags; +} + +void os::Aix::set_signal_handler(int sig, bool set_installed) { + // Check for overwrite. + struct sigaction oldAct; + sigaction(sig, (struct sigaction*)NULL, &oldAct); + + void* oldhand = oldAct.sa_sigaction + ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); + // Renamed 'signalHandler' to avoid collision with other shared libs. + if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) && + oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) && + oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)javaSignalHandler)) { + if (AllowUserSignalHandlers || !set_installed) { + // Do not overwrite; user takes responsibility to forward to us. + return; + } else if (UseSignalChaining) { + // save the old handler in jvm + save_preinstalled_handler(sig, oldAct); + // libjsig also interposes the sigaction() call below and saves the + // old sigaction on it own. + } else { + fatal(err_msg("Encountered unexpected pre-existing sigaction handler " + "%#lx for signal %d.", (long)oldhand, sig)); + } + } + + struct sigaction sigAct; + sigfillset(&(sigAct.sa_mask)); + if (!set_installed) { + sigAct.sa_handler = SIG_DFL; + sigAct.sa_flags = SA_RESTART; + } else { + // Renamed 'signalHandler' to avoid collision with other shared libs. + sigAct.sa_sigaction = javaSignalHandler; + sigAct.sa_flags = SA_SIGINFO|SA_RESTART; + } + // Save flags, which are set by ours + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigflags[sig] = sigAct.sa_flags; + + int ret = sigaction(sig, &sigAct, &oldAct); + assert(ret == 0, "check"); + + void* oldhand2 = oldAct.sa_sigaction + ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); + assert(oldhand2 == oldhand, "no concurrent signal handler installation"); +} + +// install signal handlers for signals that HotSpot needs to +// handle in order to support Java-level exception handling. +void os::Aix::install_signal_handlers() { + if (!signal_handlers_are_installed) { + signal_handlers_are_installed = true; + + // signal-chaining + typedef void (*signal_setting_t)(); + signal_setting_t begin_signal_setting = NULL; + signal_setting_t end_signal_setting = NULL; + begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t, + dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting")); + if (begin_signal_setting != NULL) { + end_signal_setting = CAST_TO_FN_PTR(signal_setting_t, + dlsym(RTLD_DEFAULT, "JVM_end_signal_setting")); + get_signal_action = CAST_TO_FN_PTR(get_signal_t, + dlsym(RTLD_DEFAULT, "JVM_get_signal_action")); + libjsig_is_loaded = true; + assert(UseSignalChaining, "should enable signal-chaining"); + } + if (libjsig_is_loaded) { + // Tell libjsig jvm is setting signal handlers + (*begin_signal_setting)(); + } + + set_signal_handler(SIGSEGV, true); + set_signal_handler(SIGPIPE, true); + set_signal_handler(SIGBUS, true); + set_signal_handler(SIGILL, true); + set_signal_handler(SIGFPE, true); + set_signal_handler(SIGTRAP, true); + set_signal_handler(SIGXFSZ, true); + set_signal_handler(SIGDANGER, true); + + if (libjsig_is_loaded) { + // Tell libjsig jvm finishes setting signal handlers + (*end_signal_setting)(); + } + + // We don't activate signal checker if libjsig is in place, we trust ourselves + // and if UserSignalHandler is installed all bets are off. + // Log that signal checking is off only if -verbose:jni is specified. + if (CheckJNICalls) { + if (libjsig_is_loaded) { + tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + check_signals = false; + } + if (AllowUserSignalHandlers) { + tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + check_signals = false; + } + // need to initialize check_signal_done + ::sigemptyset(&check_signal_done); + } + } +} + +static const char* get_signal_handler_name(address handler, + char* buf, int buflen) { + int offset; + bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset); + if (found) { + // skip directory names + const char *p1, *p2; + p1 = buf; + size_t len = strlen(os::file_separator()); + while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len; + // The way os::dll_address_to_library_name is implemented on Aix + // right now, it always returns -1 for the offset which is not + // terribly informative. + // Will fix that. For now, omit the offset. + jio_snprintf(buf, buflen, "%s", p1); + } else { + jio_snprintf(buf, buflen, PTR_FORMAT, handler); + } + return buf; +} + +static void print_signal_handler(outputStream* st, int sig, + char* buf, size_t buflen) { + struct sigaction sa; + sigaction(sig, NULL, &sa); + + st->print("%s: ", os::exception_name(sig, buf, buflen)); + + address handler = (sa.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) + : CAST_FROM_FN_PTR(address, sa.sa_handler); + + if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) { + st->print("SIG_DFL"); + } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) { + st->print("SIG_IGN"); + } else { + st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); + } + + // Print readable mask. + st->print(", sa_mask[0]="); + os::Posix::print_signal_set_short(st, &sa.sa_mask); + + address rh = VMError::get_resetted_sighandler(sig); + // May be, handler was resetted by VMError? + if (rh != NULL) { + handler = rh; + sa.sa_flags = VMError::get_resetted_sigflags(sig); + } + + // Print textual representation of sa_flags. + st->print(", sa_flags="); + os::Posix::print_sa_flags(st, sa.sa_flags); + + // Check: is it our handler? + if (handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)javaSignalHandler) || + handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) { + // It is our signal handler. + // Check for flags, reset system-used one! + if ((int)sa.sa_flags != os::Aix::get_our_sigflags(sig)) { + st->print(", flags was changed from " PTR32_FORMAT ", consider using jsig library", + os::Aix::get_our_sigflags(sig)); + } + } + st->cr(); +} + + +#define DO_SIGNAL_CHECK(sig) \ + if (!sigismember(&check_signal_done, sig)) \ + os::Aix::check_signal_handler(sig) + +// This method is a periodic task to check for misbehaving JNI applications +// under CheckJNI, we can add any periodic checks here + +void os::run_periodic_checks() { + + if (check_signals == false) return; + + // SEGV and BUS if overridden could potentially prevent + // generation of hs*.log in the event of a crash, debugging + // such a case can be very challenging, so we absolutely + // check the following for a good measure: + DO_SIGNAL_CHECK(SIGSEGV); + DO_SIGNAL_CHECK(SIGILL); + DO_SIGNAL_CHECK(SIGFPE); + DO_SIGNAL_CHECK(SIGBUS); + DO_SIGNAL_CHECK(SIGPIPE); + DO_SIGNAL_CHECK(SIGXFSZ); + if (UseSIGTRAP) { + DO_SIGNAL_CHECK(SIGTRAP); + } + DO_SIGNAL_CHECK(SIGDANGER); + + // ReduceSignalUsage allows the user to override these handlers + // see comments at the very top and jvm_solaris.h + if (!ReduceSignalUsage) { + DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL); + DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL); + DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL); + DO_SIGNAL_CHECK(BREAK_SIGNAL); + } + + DO_SIGNAL_CHECK(SR_signum); + DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); +} + +typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); + +static os_sigaction_t os_sigaction = NULL; + +void os::Aix::check_signal_handler(int sig) { + char buf[O_BUFLEN]; + address jvmHandler = NULL; + + struct sigaction act; + if (os_sigaction == NULL) { + // only trust the default sigaction, in case it has been interposed + os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction"); + if (os_sigaction == NULL) return; + } + + os_sigaction(sig, (struct sigaction*)NULL, &act); + + address thisHandler = (act.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, act.sa_sigaction) + : CAST_FROM_FN_PTR(address, act.sa_handler); + + + switch(sig) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGPIPE: + case SIGILL: + case SIGXFSZ: + // Renamed 'signalHandler' to avoid collision with other shared libs. + jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)javaSignalHandler); + break; + + case SHUTDOWN1_SIGNAL: + case SHUTDOWN2_SIGNAL: + case SHUTDOWN3_SIGNAL: + case BREAK_SIGNAL: + jvmHandler = (address)user_handler(); + break; + + case INTERRUPT_SIGNAL: + jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); + break; + + default: + if (sig == SR_signum) { + jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); + } else { + return; + } + break; + } + + if (thisHandler != jvmHandler) { + tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN)); + tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN)); + tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); + // No need to check this sig any longer + sigaddset(&check_signal_done, sig); + } else if (os::Aix::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Aix::get_our_sigflags(sig)) { + tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); + tty->print("expected:" PTR32_FORMAT, os::Aix::get_our_sigflags(sig)); + tty->print_cr(" found:" PTR32_FORMAT, act.sa_flags); + // No need to check this sig any longer + sigaddset(&check_signal_done, sig); + } + + // Dump all the signal + if (sigismember(&check_signal_done, sig)) { + print_signal_handlers(tty, buf, O_BUFLEN); + } +} + +extern bool signal_name(int signo, char* buf, size_t len); + +const char* os::exception_name(int exception_code, char* buf, size_t size) { + if (0 < exception_code && exception_code <= SIGRTMAX) { + // signal + if (!signal_name(exception_code, buf, size)) { + jio_snprintf(buf, size, "SIG%d", exception_code); + } + return buf; + } else { + return NULL; + } +} + +// To install functions for atexit system call +extern "C" { + static void perfMemory_exit_helper() { + perfMemory_exit(); + } +} + +// This is called _before_ the most of global arguments have been parsed. +void os::init(void) { + // This is basic, we want to know if that ever changes. + // (shared memory boundary is supposed to be a 256M aligned) + assert(SHMLBA == ((uint64_t)0x10000000ULL)/*256M*/, "unexpected"); + + // First off, we need to know whether we run on AIX or PASE, and + // the OS level we run on. + os::Aix::initialize_os_info(); + + // Scan environment (SPEC1170 behaviour, etc) + os::Aix::scan_environment(); + + // Check which pages are supported by AIX. + os::Aix::query_multipage_support(); + + // Next, we need to initialize libo4 and libperfstat libraries. + if (os::Aix::on_pase()) { + os::Aix::initialize_libo4(); + } else { + os::Aix::initialize_libperfstat(); + } + + // Reset the perfstat information provided by ODM. + if (os::Aix::on_aix()) { + libperfstat::perfstat_reset(); + } + + // Now initialze basic system properties. Note that for some of the values we + // need libperfstat etc. + os::Aix::initialize_system_info(); + + // Initialize large page support. + if (UseLargePages) { + os::large_page_init(); + if (!UseLargePages) { + // initialize os::_page_sizes + _page_sizes[0] = Aix::page_size(); + _page_sizes[1] = 0; + if (Verbose) { + fprintf(stderr, "Large Page initialization failed: setting UseLargePages=0.\n"); + } + } + } else { + // initialize os::_page_sizes + _page_sizes[0] = Aix::page_size(); + _page_sizes[1] = 0; + } + + // debug trace + if (Verbose) { + fprintf(stderr, "os::vm_page_size 0x%llX\n", os::vm_page_size()); + fprintf(stderr, "os::large_page_size 0x%llX\n", os::large_page_size()); + fprintf(stderr, "os::_page_sizes = ( "); + for (int i = 0; _page_sizes[i]; i ++) { + fprintf(stderr, " %s ", describe_pagesize(_page_sizes[i])); + } + fprintf(stderr, ")\n"); + } + + _initial_pid = getpid(); + + clock_tics_per_sec = sysconf(_SC_CLK_TCK); + + init_random(1234567); + + ThreadCritical::initialize(); + + // Main_thread points to the aboriginal thread. + Aix::_main_thread = pthread_self(); + + initial_time_count = os::elapsed_counter(); + pthread_mutex_init(&dl_mutex, NULL); +} + +// this is called _after_ the global arguments have been parsed +jint os::init_2(void) { + + if (Verbose) { + fprintf(stderr, "processor count: %d\n", os::_processor_count); + fprintf(stderr, "physical memory: %lu\n", Aix::_physical_memory); + } + + // initially build up the loaded dll map + LoadedLibraries::reload(); + + const int page_size = Aix::page_size(); + const int map_size = page_size; + + address map_address = (address) MAP_FAILED; + const int prot = PROT_READ; + const int flags = MAP_PRIVATE|MAP_ANONYMOUS; + + // use optimized addresses for the polling page, + // e.g. map it to a special 32-bit address. + if (OptimizePollingPageLocation) { + // architecture-specific list of address wishes: + address address_wishes[] = { + // AIX: addresses lower than 0x30000000 don't seem to work on AIX. + // PPC64: all address wishes are non-negative 32 bit values where + // the lower 16 bits are all zero. we can load these addresses + // with a single ppc_lis instruction. + (address) 0x30000000, (address) 0x31000000, + (address) 0x32000000, (address) 0x33000000, + (address) 0x40000000, (address) 0x41000000, + (address) 0x42000000, (address) 0x43000000, + (address) 0x50000000, (address) 0x51000000, + (address) 0x52000000, (address) 0x53000000, + (address) 0x60000000, (address) 0x61000000, + (address) 0x62000000, (address) 0x63000000 + }; + int address_wishes_length = sizeof(address_wishes)/sizeof(address); + + // iterate over the list of address wishes: + for (int i=0; i %p\n", + address_wishes[i], map_address + (ssize_t)page_size); + } + + if (map_address + (ssize_t)page_size == address_wishes[i]) { + // map succeeded and map_address is at wished address, exit loop. + break; + } + + if (map_address != (address) MAP_FAILED) { + // map succeeded, but polling_page is not at wished address, unmap and continue. + ::munmap(map_address, map_size); + map_address = (address) MAP_FAILED; + } + // map failed, continue loop. + } + } // end OptimizePollingPageLocation + + if (map_address == (address) MAP_FAILED) { + map_address = (address) ::mmap(NULL, map_size, prot, flags, -1, 0); + } + guarantee(map_address != MAP_FAILED, "os::init_2: failed to allocate polling page"); + os::set_polling_page(map_address); + + if (!UseMembar) { + address mem_serialize_page = (address) ::mmap(NULL, Aix::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + guarantee(mem_serialize_page != NULL, "mmap Failed for memory serialize page"); + os::set_memory_serialize_page(mem_serialize_page); + +#ifndef PRODUCT + if (Verbose && PrintMiscellaneous) + tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); +#endif + } + + // initialize suspend/resume support - must do this before signal_sets_init() + if (SR_initialize() != 0) { + perror("SR_initialize failed"); + return JNI_ERR; + } + + Aix::signal_sets_init(); + Aix::install_signal_handlers(); + + // Check minimum allowable stack size for thread creation and to initialize + // the java system classes, including StackOverflowError - depends on page + // size. Add a page for compiler2 recursion in main thread. + // Add in 2*BytesPerWord times page size to account for VM stack during + // class initialization depending on 32 or 64 bit VM. + os::Aix::min_stack_allowed = MAX2(os::Aix::min_stack_allowed, + (size_t)(StackYellowPages+StackRedPages+StackShadowPages + + 2*BytesPerWord COMPILER2_PRESENT(+1)) * Aix::page_size()); + + size_t threadStackSizeInBytes = ThreadStackSize * K; + if (threadStackSizeInBytes != 0 && + threadStackSizeInBytes < os::Aix::min_stack_allowed) { + tty->print_cr("\nThe stack size specified is too small, " + "Specify at least %dk", + os::Aix::min_stack_allowed / K); + return JNI_ERR; + } + + // Make the stack size a multiple of the page size so that + // the yellow/red zones can be guarded. + // note that this can be 0, if no default stacksize was set + JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size())); + + Aix::libpthread_init(); + + if (MaxFDLimit) { + // set the number of file descriptors to max. print out error + // if getrlimit/setrlimit fails but continue regardless. + struct rlimit nbr_files; + int status = getrlimit(RLIMIT_NOFILE, &nbr_files); + if (status != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) + perror("os::init_2 getrlimit failed"); + } else { + nbr_files.rlim_cur = nbr_files.rlim_max; + status = setrlimit(RLIMIT_NOFILE, &nbr_files); + if (status != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) + perror("os::init_2 setrlimit failed"); + } + } + } + + if (PerfAllowAtExitRegistration) { + // only register atexit functions if PerfAllowAtExitRegistration is set. + // atexit functions can be delayed until process exit time, which + // can be problematic for embedded VM situations. Embedded VMs should + // call DestroyJavaVM() to assure that VM resources are released. + + // note: perfMemory_exit_helper atexit function may be removed in + // the future if the appropriate cleanup code can be added to the + // VM_Exit VMOperation's doit method. + if (atexit(perfMemory_exit_helper) != 0) { + warning("os::init_2 atexit(perfMemory_exit_helper) failed"); + } + } + + return JNI_OK; +} + +// this is called at the end of vm_initialization +void os::init_3(void) { + return; +} + +// Mark the polling page as unreadable +void os::make_polling_page_unreadable(void) { + if (!guard_memory((char*)_polling_page, Aix::page_size())) { + fatal("Could not disable polling page"); + } +}; + +// Mark the polling page as readable +void os::make_polling_page_readable(void) { + // Changed according to os_linux.cpp. + if (!checked_mprotect((char *)_polling_page, Aix::page_size(), PROT_READ)) { + fatal(err_msg("Could not enable polling page at " PTR_FORMAT, _polling_page)); + } +}; + +int os::active_processor_count() { + int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); + assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check"); + return online_cpus; +} + +void os::set_native_thread_name(const char *name) { + // Not yet implemented. + return; +} + +bool os::distribute_processes(uint length, uint* distribution) { + // Not yet implemented. + return false; +} + +bool os::bind_to_processor(uint processor_id) { + // Not yet implemented. + return false; +} + +void os::SuspendedThreadTask::internal_do_task() { + if (do_suspend(_thread->osthread())) { + SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); + do_task(context); + do_resume(_thread->osthread()); + } +} + +class PcFetcher : public os::SuspendedThreadTask { +public: + PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} + ExtendedPC result(); +protected: + void do_task(const os::SuspendedThreadTaskContext& context); +private: + ExtendedPC _epc; +}; + +ExtendedPC PcFetcher::result() { + guarantee(is_done(), "task is not done yet."); + return _epc; +} + +void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { + Thread* thread = context.thread(); + OSThread* osthread = thread->osthread(); + if (osthread->ucontext() != NULL) { + _epc = os::Aix::ucontext_get_pc((ucontext_t *) context.ucontext()); + } else { + // NULL context is unexpected, double-check this is the VMThread. + guarantee(thread->is_VM_thread(), "can only be called for VMThread"); + } +} + +// Suspends the target using the signal mechanism and then grabs the PC before +// resuming the target. Used by the flat-profiler only +ExtendedPC os::get_thread_pc(Thread* thread) { + // Make sure that it is called by the watcher for the VMThread. + assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); + assert(thread->is_VM_thread(), "Can only be called for VMThread"); + + PcFetcher fetcher(thread); + fetcher.run(); + return fetcher.result(); +} + +// Not neede on Aix. +// int os::Aix::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) { +// } + +//////////////////////////////////////////////////////////////////////////////// +// debug support + +static address same_page(address x, address y) { + intptr_t page_bits = -os::vm_page_size(); + if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) + return x; + else if (x > y) + return (address)(intptr_t(y) | ~page_bits) + 1; + else + return (address)(intptr_t(y) & page_bits); +} + +bool os::find(address addr, outputStream* st) { + Unimplemented(); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// misc + +// This does not do anything on Aix. This is basically a hook for being +// able to use structured exception handling (thread-local exception filters) +// on, e.g., Win32. +void +os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, + JavaCallArguments* args, Thread* thread) { + f(value, method, args, thread); +} + +void os::print_statistics() { +} + +int os::message_box(const char* title, const char* message) { + int i; + fdStream err(defaultStream::error_fd()); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + err.print_raw_cr(title); + for (i = 0; i < 78; i++) err.print_raw("-"); + err.cr(); + err.print_raw_cr(message); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + + char buf[16]; + // Prevent process from exiting upon "read error" without consuming all CPU + while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } + + return buf[0] == 'y' || buf[0] == 'Y'; +} + +int os::stat(const char *path, struct stat *sbuf) { + char pathbuf[MAX_PATH]; + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::stat(pathbuf, sbuf); +} + +bool os::check_heap(bool force) { + return true; +} + +// int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) { +// return ::vsnprintf(buf, count, format, args); +// } + +// Is a (classpath) directory empty? +bool os::dir_is_empty(const char* path) { + Unimplemented(); + return false; +} + +// This code originates from JDK's sysOpen and open64_w +// from src/solaris/hpi/src/system_md.c + +#ifndef O_DELETE +#define O_DELETE 0x10000 +#endif + +// Open a file. Unlink the file immediately after open returns +// if the specified oflag has the O_DELETE flag set. +// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c + +int os::open(const char *path, int oflag, int mode) { + + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + int fd; + int o_delete = (oflag & O_DELETE); + oflag = oflag & ~O_DELETE; + + fd = ::open64(path, oflag, mode); + if (fd == -1) return -1; + + //If the open succeeded, the file might still be a directory + { + struct stat64 buf64; + int ret = ::fstat64(fd, &buf64); + int st_mode = buf64.st_mode; + + if (ret != -1) { + if ((st_mode & S_IFMT) == S_IFDIR) { + errno = EISDIR; + ::close(fd); + return -1; + } + } else { + ::close(fd); + return -1; + } + } + + // All file descriptors that are opened in the JVM and not + // specifically destined for a subprocess should have the + // close-on-exec flag set. If we don't set it, then careless 3rd + // party native code might fork and exec without closing all + // appropriate file descriptors (e.g. as we do in closeDescriptors in + // UNIXProcess.c), and this in turn might: + // + // - cause end-of-file to fail to be detected on some file + // descriptors, resulting in mysterious hangs, or + // + // - might cause an fopen in the subprocess to fail on a system + // suffering from bug 1085341. + // + // (Yes, the default setting of the close-on-exec flag is a Unix + // design flaw.) + // + // See: + // 1085341: 32-bit stdio routines should support file descriptors >255 + // 4843136: (process) pipe file descriptor from Runtime.exec not being closed + // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 +#ifdef FD_CLOEXEC + { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + if (o_delete != 0) { + ::unlink(path); + } + return fd; +} + + +// create binary file, rewriting existing file if required +int os::create_binary_file(const char* path, bool rewrite_existing) { + Unimplemented(); + return 0; +} + +// return current position of file pointer +jlong os::current_file_offset(int fd) { + return (jlong)::lseek64(fd, (off64_t)0, SEEK_CUR); +} + +// move file pointer to the specified offset +jlong os::seek_to_file_offset(int fd, jlong offset) { + return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET); +} + +// This code originates from JDK's sysAvailable +// from src/solaris/hpi/src/native_threads/src/sys_api_td.c + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + int mode; + struct stat64 buf64; + + if (::fstat64(fd, &buf64) >= 0) { + mode = buf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { + // XXX: is the following call interruptible? If so, this might + // need to go through the INTERRUPT_IO() wrapper as for other + // blocking, interruptible calls in this file. + int n; + if (::ioctl(fd, FIONREAD, &n) >= 0) { + *bytes = n; + return 1; + } + } + } + if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) { + return 0; + } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) { + return 0; + } else if (::lseek64(fd, cur, SEEK_SET) == -1) { + return 0; + } + *bytes = end - cur; + return 1; +} + +int os::socket_available(int fd, jint *pbytes) { + // Linux doc says EINTR not returned, unlike Solaris + int ret = ::ioctl(fd, FIONREAD, pbytes); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + return (ret < 0) ? 0 : 1; +} + +// Map a block of memory. +char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec) { + Unimplemented(); + return NULL; +} + + +// Remap a block of memory. +char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec) { + // same as map_memory() on this OS + return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only, + allow_exec); +} + +// Unmap a block of memory. +bool os::pd_unmap_memory(char* addr, size_t bytes) { + return munmap(addr, bytes) == 0; +} + +// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) +// are used by JVM M&M and JVMTI to get user+sys or user CPU time +// of a thread. +// +// current_thread_cpu_time() and thread_cpu_time(Thread*) returns +// the fast estimate available on the platform. + +jlong os::current_thread_cpu_time() { + // return user + sys since the cost is the same + const jlong n = os::thread_cpu_time(Thread::current(), true /* user + sys */); + assert(n >= 0, "negative CPU time"); + return n; +} + +jlong os::thread_cpu_time(Thread* thread) { + // consistent with what current_thread_cpu_time() returns + const jlong n = os::thread_cpu_time(thread, true /* user + sys */); + assert(n >= 0, "negative CPU time"); + return n; +} + +jlong os::current_thread_cpu_time(bool user_sys_cpu_time) { + const jlong n = os::thread_cpu_time(Thread::current(), user_sys_cpu_time); + assert(n >= 0, "negative CPU time"); + return n; +} + +static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* p_user_time) { + bool error = false; + + jlong sys_time = 0; + jlong user_time = 0; + + // reimplemented using getthrds64(). + // + // goes like this: + // For the thread in question, get the kernel thread id. Then get the + // kernel thread statistics using that id. + // + // This only works of course when no pthread scheduling is used, + // ie there is a 1:1 relationship to kernel threads. + // On AIX, see AIXTHREAD_SCOPE variable. + + pthread_t pthtid = thread->osthread()->pthread_id(); + + // retrieve kernel thread id for the pthread: + tid64_t tid = 0; + struct __pthrdsinfo pinfo; + // I just love those otherworldly IBM APIs which force me to hand down + // dummy buffers for stuff I dont care for... + char dummy[1]; + int dummy_size = sizeof(dummy); + if (pthread_getthrds_np(&pthtid, PTHRDSINFO_QUERY_TID, &pinfo, sizeof(pinfo), + dummy, &dummy_size) == 0) { + tid = pinfo.__pi_tid; + } else { + tty->print_cr("pthread_getthrds_np failed."); + error = true; + } + + // retrieve kernel timing info for that kernel thread + if (!error) { + struct thrdentry64 thrdentry; + if (getthrds64(getpid(), &thrdentry, sizeof(thrdentry), &tid, 1) == 1) { + sys_time = thrdentry.ti_ru.ru_stime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_stime.tv_usec * 1000LL; + user_time = thrdentry.ti_ru.ru_utime.tv_sec * 1000000000LL + thrdentry.ti_ru.ru_utime.tv_usec * 1000LL; + } else { + tty->print_cr("pthread_getthrds_np failed."); + error = true; + } + } + + if (p_sys_time) { + *p_sys_time = sys_time; + } + + if (p_user_time) { + *p_user_time = user_time; + } + + if (error) { + return false; + } + + return true; +} + +jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { + jlong sys_time; + jlong user_time; + + if (!thread_cpu_time_unchecked(thread, &sys_time, &user_time)) { + return -1; + } + + return user_sys_cpu_time ? sys_time + user_time : user_time; +} + +void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits + info_ptr->may_skip_backward = false; // elapsed time not wall time + info_ptr->may_skip_forward = false; // elapsed time not wall time + info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned +} + +void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits + info_ptr->may_skip_backward = false; // elapsed time not wall time + info_ptr->may_skip_forward = false; // elapsed time not wall time + info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned +} + +bool os::is_thread_cpu_time_supported() { + return true; +} + +// System loadavg support. Returns -1 if load average cannot be obtained. +// For now just return the system wide load average (no processor sets). +int os::loadavg(double values[], int nelem) { + + // Implemented using libperfstat on AIX. + + guarantee(nelem >= 0 && nelem <= 3, "argument error"); + guarantee(values, "argument error"); + + if (os::Aix::on_pase()) { + Unimplemented(); + return -1; + } else { + // AIX: use libperfstat + // + // See also: + // http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/perfstat_cputot.htm + // /usr/include/libperfstat.h: + + // Use the already AIX version independent get_cpuinfo. + os::Aix::cpuinfo_t ci; + if (os::Aix::get_cpuinfo(&ci)) { + for (int i = 0; i < nelem; i++) { + values[i] = ci.loadavg[i]; + } + } else { + return -1; + } + return nelem; + } +} + +void os::pause() { + char filename[MAX_PATH]; + if (PauseAtStartupFile && PauseAtStartupFile[0]) { + jio_snprintf(filename, MAX_PATH, PauseAtStartupFile); + } else { + jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id()); + } + + int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd != -1) { + struct stat buf; + ::close(fd); + while (::stat(filename, &buf) == 0) { + (void)::poll(NULL, 0, 100); + } + } else { + jio_fprintf(stderr, + "Could not open pause file '%s', continuing immediately.\n", filename); + } +} + +bool os::Aix::is_primordial_thread() { + if (pthread_self() == (pthread_t)1) { + return true; + } else { + return false; + } +} + +// OS recognitions (PASE/AIX, OS level) call this before calling any +// one of Aix::on_pase(), Aix::os_version() static +void os::Aix::initialize_os_info() { + + assert(_on_pase == -1 && _os_version == -1, "already called."); + + struct utsname uts; + memset(&uts, 0, sizeof(uts)); + strcpy(uts.sysname, "?"); + if (::uname(&uts) == -1) { + fprintf(stderr, "uname failed (%d)\n", errno); + guarantee(0, "Could not determine whether we run on AIX or PASE"); + } else { + if (Verbose) { + fprintf(stderr,"uname says: sysname \"%s\" version \"%s\" release \"%s\" " + "node \"%s\" machine \"%s\"\n", + uts.sysname, uts.version, uts.release, uts.nodename, uts.machine); + } + const int major = atoi(uts.version); + assert(major > 0, "invalid OS version"); + const int minor = atoi(uts.release); + assert(minor > 0, "invalid OS release"); + _os_version = (major << 8) | minor; + if (strcmp(uts.sysname, "OS400") == 0) { + Unimplemented(); + } else if (strcmp(uts.sysname, "AIX") == 0) { + // We run on AIX. We do not support versions older than AIX 5.3. + _on_pase = 0; + if (_os_version < 0x0503) { + fprintf(stderr, "AIX release older than AIX 5.3 not supported.\n"); + assert(false, "AIX release too old."); + } else { + if (Verbose) { + fprintf(stderr, "We run on AIX %d.%d\n", major, minor); + } + } + } else { + assert(false, "unknown OS"); + } + } + + guarantee(_on_pase != -1 && _os_version, "Could not determine AIX/OS400 release"); + +} // end: os::Aix::initialize_os_info() + +// Scan environment for important settings which might effect the VM. +// Trace out settings. Warn about invalid settings and/or correct them. +// +// Must run after os::Aix::initialue_os_info(). +void os::Aix::scan_environment() { + + char* p; + int rc; + + // Warn explicity if EXTSHM=ON is used. That switch changes how + // System V shared memory behaves. One effect is that page size of + // shared memory cannot be change dynamically, effectivly preventing + // large pages from working. + // This switch was needed on AIX 32bit, but on AIX 64bit the general + // recommendation is (in OSS notes) to switch it off. + p = ::getenv("EXTSHM"); + if (Verbose) { + fprintf(stderr, "EXTSHM=%s.\n", p ? p : ""); + } + if (p && strcmp(p, "ON") == 0) { + fprintf(stderr, "Unsupported setting: EXTSHM=ON. Large Page support will be disabled.\n"); + _extshm = 1; + } else { + _extshm = 0; + } + + // SPEC1170 behaviour: will change the behaviour of a number of POSIX APIs. + // Not tested, not supported. + // + // Note that it might be worth the trouble to test and to require it, if only to + // get useful return codes for mprotect. + // + // Note: Setting XPG_SUS_ENV in the process is too late. Must be set earlier (before + // exec() ? before loading the libjvm ? ....) + p = ::getenv("XPG_SUS_ENV"); + if (Verbose) { + fprintf(stderr, "XPG_SUS_ENV=%s.\n", p ? p : ""); + } + if (p && strcmp(p, "ON") == 0) { + _xpg_sus_mode = 1; + fprintf(stderr, "Unsupported setting: XPG_SUS_ENV=ON\n"); + // This is not supported. Worst of all, it changes behaviour of mmap MAP_FIXED to + // clobber address ranges. If we ever want to support that, we have to do some + // testing first. + guarantee(false, "XPG_SUS_ENV=ON not supported"); + } else { + _xpg_sus_mode = 0; + } + + // Switch off AIX internal (pthread) guard pages. This has + // immediate effect for any pthread_create calls which follow. + p = ::getenv("AIXTHREAD_GUARDPAGES"); + if (Verbose) { + fprintf(stderr, "AIXTHREAD_GUARDPAGES=%s.\n", p ? p : ""); + fprintf(stderr, "setting AIXTHREAD_GUARDPAGES=0.\n"); + } + rc = ::putenv("AIXTHREAD_GUARDPAGES=0"); + guarantee(rc == 0, ""); + +} // end: os::Aix::scan_environment() + +// PASE: initialize the libo4 library (AS400 PASE porting library). +void os::Aix::initialize_libo4() { + Unimplemented(); +} + +// AIX: initialize the libperfstat library (we load this dynamically +// because it is only available on AIX. +void os::Aix::initialize_libperfstat() { + + assert(os::Aix::on_aix(), "AIX only"); + + if (!libperfstat::init()) { + fprintf(stderr, "libperfstat initialization failed.\n"); + assert(false, "libperfstat initialization failed"); + } else { + if (Verbose) { + fprintf(stderr, "libperfstat initialized.\n"); + } + } +} // end: os::Aix::initialize_libperfstat + +///////////////////////////////////////////////////////////////////////////// +// thread stack + +// function to query the current stack size using pthread_getthrds_np +// +// ! do not change anything here unless you know what you are doing ! +static void query_stack_dimensions(address* p_stack_base, size_t* p_stack_size) { + + // This only works when invoked on a pthread. As we agreed not to use + // primordial threads anyway, I assert here + guarantee(!os::Aix::is_primordial_thread(), "not allowed on the primordial thread"); + + // information about this api can be found (a) in the pthread.h header and + // (b) in http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/pthread_getthrds_np.htm + // + // The use of this API to find out the current stack is kind of undefined. + // But after a lot of tries and asking IBM about it, I concluded that it is safe + // enough for cases where I let the pthread library create its stacks. For cases + // where I create an own stack and pass this to pthread_create, it seems not to + // work (the returned stack size in that case is 0). + + pthread_t tid = pthread_self(); + struct __pthrdsinfo pinfo; + char dummy[1]; // we only need this to satisfy the api and to not get E + int dummy_size = sizeof(dummy); + + memset(&pinfo, 0, sizeof(pinfo)); + + const int rc = pthread_getthrds_np (&tid, PTHRDSINFO_QUERY_ALL, &pinfo, + sizeof(pinfo), dummy, &dummy_size); + + if (rc != 0) { + fprintf(stderr, "pthread_getthrds_np failed (%d)\n", rc); + guarantee(0, "pthread_getthrds_np failed"); + } + + guarantee(pinfo.__pi_stackend, "returned stack base invalid"); + + // the following can happen when invoking pthread_getthrds_np on a pthread running on a user provided stack + // (when handing down a stack to pthread create, see pthread_attr_setstackaddr). + // Not sure what to do here - I feel inclined to forbid this use case completely. + guarantee(pinfo.__pi_stacksize, "returned stack size invalid"); + + // On AIX, stacks are not necessarily page aligned so round the base and size accordingly + if (p_stack_base) { + (*p_stack_base) = (address) align_size_up((intptr_t)pinfo.__pi_stackend, os::Aix::stack_page_size()); + } + + if (p_stack_size) { + (*p_stack_size) = pinfo.__pi_stacksize - os::Aix::stack_page_size(); + } + +#ifndef PRODUCT + if (Verbose) { + fprintf(stderr, + "query_stack_dimensions() -> real stack_base=" INTPTR_FORMAT ", real stack_addr=" INTPTR_FORMAT + ", real stack_size=" INTPTR_FORMAT + ", stack_base=" INTPTR_FORMAT ", stack_size=" INTPTR_FORMAT "\n", + (intptr_t)pinfo.__pi_stackend, (intptr_t)pinfo.__pi_stackaddr, pinfo.__pi_stacksize, + (intptr_t)align_size_up((intptr_t)pinfo.__pi_stackend, os::Aix::stack_page_size()), + pinfo.__pi_stacksize - os::Aix::stack_page_size()); + } +#endif + +} // end query_stack_dimensions + +// get the current stack base from the OS (actually, the pthread library) +address os::current_stack_base() { + address p; + query_stack_dimensions(&p, 0); + return p; +} + +// get the current stack size from the OS (actually, the pthread library) +size_t os::current_stack_size() { + size_t s; + query_stack_dimensions(0, &s); + return s; +} + +// Refer to the comments in os_solaris.cpp park-unpark. +// +// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can +// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable. +// For specifics regarding the bug see GLIBC BUGID 261237 : +// http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html. +// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future +// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar +// is used. (The simple C test-case provided in the GLIBC bug report manifests the +// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos() +// and monitorenter when we're using 1-0 locking. All those operations may result in +// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version +// of libpthread avoids the problem, but isn't practical. +// +// Possible remedies: +// +// 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work. +// This is palliative and probabilistic, however. If the thread is preempted +// between the call to compute_abstime() and pthread_cond_timedwait(), more +// than the minimum period may have passed, and the abstime may be stale (in the +// past) resultin in a hang. Using this technique reduces the odds of a hang +// but the JVM is still vulnerable, particularly on heavily loaded systems. +// +// 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead +// of the usual flag-condvar-mutex idiom. The write side of the pipe is set +// NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo) +// reduces to poll()+read(). This works well, but consumes 2 FDs per extant +// thread. +// +// 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread +// that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing +// a timeout request to the chron thread and then blocking via pthread_cond_wait(). +// This also works well. In fact it avoids kernel-level scalability impediments +// on certain platforms that don't handle lots of active pthread_cond_timedwait() +// timers in a graceful fashion. +// +// 4. When the abstime value is in the past it appears that control returns +// correctly from pthread_cond_timedwait(), but the condvar is left corrupt. +// Subsequent timedwait/wait calls may hang indefinitely. Given that, we +// can avoid the problem by reinitializing the condvar -- by cond_destroy() +// followed by cond_init() -- after all calls to pthread_cond_timedwait(). +// It may be possible to avoid reinitialization by checking the return +// value from pthread_cond_timedwait(). In addition to reinitializing the +// condvar we must establish the invariant that cond_signal() is only called +// within critical sections protected by the adjunct mutex. This prevents +// cond_signal() from "seeing" a condvar that's in the midst of being +// reinitialized or that is corrupt. Sadly, this invariant obviates the +// desirable signal-after-unlock optimization that avoids futile context switching. +// +// I'm also concerned that some versions of NTPL might allocate an auxilliary +// structure when a condvar is used or initialized. cond_destroy() would +// release the helper structure. Our reinitialize-after-timedwait fix +// put excessive stress on malloc/free and locks protecting the c-heap. +// +// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag. +// It may be possible to refine (4) by checking the kernel and NTPL verisons +// and only enabling the work-around for vulnerable environments. + +// utility to compute the abstime argument to timedwait: +// millis is the relative timeout time +// abstime will be the absolute timeout time +// TODO: replace compute_abstime() with unpackTime() + +static struct timespec* compute_abstime(timespec* abstime, jlong millis) { + if (millis < 0) millis = 0; + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + jlong seconds = millis / 1000; + millis %= 1000; + if (seconds > 50000000) { // see man cond_timedwait(3T) + seconds = 50000000; + } + abstime->tv_sec = now.tv_sec + seconds; + long usec = now.tv_usec + millis * 1000; + if (usec >= 1000000) { + abstime->tv_sec += 1; + usec -= 1000000; + } + abstime->tv_nsec = usec * 1000; + return abstime; +} + + +// Test-and-clear _Event, always leaves _Event set to 0, returns immediately. +// Conceptually TryPark() should be equivalent to park(0). + +int os::PlatformEvent::TryPark() { + for (;;) { + const int v = _Event; + guarantee ((v == 0) || (v == 1), "invariant"); + if (Atomic::cmpxchg (0, &_Event, v) == v) return v; + } +} + +void os::PlatformEvent::park() { // AKA "down()" + // Invariant: Only the thread associated with the Event/PlatformEvent + // may call park(). + // TODO: assert that _Assoc != NULL or _Assoc == Self + int v; + for (;;) { + v = _Event; + if (Atomic::cmpxchg (v-1, &_Event, v) == v) break; + } + guarantee (v >= 0, "invariant"); + if (v == 0) { + // Do this the hard way by blocking ... + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + guarantee (_nParked == 0, "invariant"); + ++ _nParked; + while (_Event < 0) { + status = pthread_cond_wait(_cond, _mutex); + assert_status(status == 0 || status == ETIMEDOUT, status, "cond_timedwait"); + } + -- _nParked; + + // In theory we could move the ST of 0 into _Event past the unlock(), + // but then we'd need a MEMBAR after the ST. + _Event = 0; + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + } + guarantee (_Event >= 0, "invariant"); +} + +int os::PlatformEvent::park(jlong millis) { + guarantee (_nParked == 0, "invariant"); + + int v; + for (;;) { + v = _Event; + if (Atomic::cmpxchg (v-1, &_Event, v) == v) break; + } + guarantee (v >= 0, "invariant"); + if (v != 0) return OS_OK; + + // We do this the hard way, by blocking the thread. + // Consider enforcing a minimum timeout value. + struct timespec abst; + compute_abstime(&abst, millis); + + int ret = OS_TIMEOUT; + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + guarantee (_nParked == 0, "invariant"); + ++_nParked; + + // Object.wait(timo) will return because of + // (a) notification + // (b) timeout + // (c) thread.interrupt + // + // Thread.interrupt and object.notify{All} both call Event::set. + // That is, we treat thread.interrupt as a special case of notification. + // The underlying Solaris implementation, cond_timedwait, admits + // spurious/premature wakeups, but the JLS/JVM spec prevents the + // JVM from making those visible to Java code. As such, we must + // filter out spurious wakeups. We assume all ETIME returns are valid. + // + // TODO: properly differentiate simultaneous notify+interrupt. + // In that case, we should propagate the notify to another waiter. + + while (_Event < 0) { + status = pthread_cond_timedwait(_cond, _mutex, &abst); + assert_status(status == 0 || status == ETIMEDOUT, + status, "cond_timedwait"); + if (!FilterSpuriousWakeups) break; // previous semantics + if (status == ETIMEDOUT) break; + // We consume and ignore EINTR and spurious wakeups. + } + --_nParked; + if (_Event >= 0) { + ret = OS_OK; + } + _Event = 0; + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + assert (_nParked == 0, "invariant"); + return ret; +} + +void os::PlatformEvent::unpark() { + int v, AnyWaiters; + for (;;) { + v = _Event; + if (v > 0) { + // The LD of _Event could have reordered or be satisfied + // by a read-aside from this processor's write buffer. + // To avoid problems execute a barrier and then + // ratify the value. + OrderAccess::fence(); + if (_Event == v) return; + continue; + } + if (Atomic::cmpxchg (v+1, &_Event, v) == v) break; + } + if (v < 0) { + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + AnyWaiters = _nParked; + + if (AnyWaiters != 0) { + // We intentional signal *after* dropping the lock + // to avoid a common class of futile wakeups. + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); + } + // Mutex should be locked for pthread_cond_signal(_cond). + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + } + + // Note that we signal() _after dropping the lock for "immortal" Events. + // This is safe and avoids a common class of futile wakeups. In rare + // circumstances this can cause a thread to return prematurely from + // cond_{timed}wait() but the spurious wakeup is benign and the victim will + // simply re-test the condition and re-park itself. +} + + +// JSR166 +// ------------------------------------------------------- + +// +// The solaris and linux implementations of park/unpark are fairly +// conservative for now, but can be improved. They currently use a +// mutex/condvar pair, plus a a count. +// Park decrements count if > 0, else does a condvar wait. Unpark +// sets count to 1 and signals condvar. Only one thread ever waits +// on the condvar. Contention seen when trying to park implies that someone +// is unparking you, so don't wait. And spurious returns are fine, so there +// is no need to track notifications. +// + +#define MAX_SECS 100000000 +// +// This code is common to linux and solaris and will be moved to a +// common place in dolphin. +// +// The passed in time value is either a relative time in nanoseconds +// or an absolute time in milliseconds. Either way it has to be unpacked +// into suitable seconds and nanoseconds components and stored in the +// given timespec structure. +// Given time is a 64-bit value and the time_t used in the timespec is only +// a signed-32-bit value (except on 64-bit Linux) we have to watch for +// overflow if times way in the future are given. Further on Solaris versions +// prior to 10 there is a restriction (see cond_timedwait) that the specified +// number of seconds, in abstime, is less than current_time + 100,000,000. +// As it will be 28 years before "now + 100000000" will overflow we can +// ignore overflow and just impose a hard-limit on seconds using the value +// of "now + 100,000,000". This places a limit on the timeout of about 3.17 +// years from "now". +// + +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { + assert (time > 0, "convertTime"); + + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + + time_t max_secs = now.tv_sec + MAX_SECS; + + if (isAbsolute) { + jlong secs = time / 1000; + if (secs > max_secs) { + absTime->tv_sec = max_secs; + } + else { + absTime->tv_sec = secs; + } + absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; + } + else { + jlong secs = time / NANOSECS_PER_SEC; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } + else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; + if (absTime->tv_nsec >= NANOSECS_PER_SEC) { + absTime->tv_nsec -= NANOSECS_PER_SEC; + ++absTime->tv_sec; // note: this must be <= max_secs + } + } + } + assert(absTime->tv_sec >= 0, "tv_sec < 0"); + assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); + assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); + assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); +} + +void Parker::park(bool isAbsolute, jlong time) { + // Optional fast-path check: + // Return immediately if a permit is available. + if (_counter > 0) { + _counter = 0; + OrderAccess::fence(); + return; + } + + Thread* thread = Thread::current(); + assert(thread->is_Java_thread(), "Must be JavaThread"); + JavaThread *jt = (JavaThread *)thread; + + // Optional optimization -- avoid state transitions if there's an interrupt pending. + // Check interrupt before trying to wait + if (Thread::is_interrupted(thread, false)) { + return; + } + + // Next, demultiplex/decode time arguments + timespec absTime; + if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all + return; + } + if (time > 0) { + unpackTime(&absTime, isAbsolute, time); + } + + + // Enter safepoint region + // Beware of deadlocks such as 6317397. + // The per-thread Parker:: mutex is a classic leaf-lock. + // In particular a thread must never block on the Threads_lock while + // holding the Parker:: mutex. If safepoints are pending both the + // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock. + ThreadBlockInVM tbivm(jt); + + // Don't wait if cannot get lock since interference arises from + // unblocking. Also. check interrupt before trying wait + if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) { + return; + } + + int status; + if (_counter > 0) { // no wait needed + _counter = 0; + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant"); + OrderAccess::fence(); + return; + } + +#ifdef ASSERT + // Don't catch signals while blocked; let the running threads have the signals. + // (This allows a debugger to break into the running thread.) + sigset_t oldsigs; + sigset_t* allowdebug_blocked = os::Aix::allowdebug_blocked_signals(); + pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); +#endif + + OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + jt->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() + + if (time == 0) { + status = pthread_cond_wait (_cond, _mutex); + } else { + status = pthread_cond_timedwait (_cond, _mutex, &absTime); + if (status != 0 && WorkAroundNPTLTimedWaitHang) { + pthread_cond_destroy (_cond); + pthread_cond_init (_cond, NULL); + } + } + assert_status(status == 0 || status == EINTR || + status == ETIME || status == ETIMEDOUT, + status, "cond_timedwait"); + +#ifdef ASSERT + pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); +#endif + + _counter = 0; + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "invariant"); + // If externally suspended while waiting, re-suspend + if (jt->handle_special_suspend_equivalent_condition()) { + jt->java_suspend_self(); + } + + OrderAccess::fence(); +} + +void Parker::unpark() { + int s, status; + status = pthread_mutex_lock(_mutex); + assert (status == 0, "invariant"); + s = _counter; + _counter = 1; + if (s < 1) { + if (WorkAroundNPTLTimedWaitHang) { + status = pthread_cond_signal (_cond); + assert (status == 0, "invariant"); + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant"); + } else { + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant"); + status = pthread_cond_signal (_cond); + assert (status == 0, "invariant"); + } + } else { + pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant"); + } +} + + +extern char** environ; + +// Run the specified command in a separate process. Return its exit value, +// or -1 on failure (e.g. can't fork a new process). +// Unlike system(), this function can be called from signal handler. It +// doesn't block SIGINT et al. +int os::fork_and_exec(char* cmd) { + Unimplemented(); + return 0; +} + +// is_headless_jre() +// +// Test for the existence of xawt/libmawt.so or libawt_xawt.so +// in order to report if we are running in a headless jre. +// +// Since JDK8 xawt/libmawt.so is moved into the same directory +// as libawt.so, and renamed libawt_xawt.so +bool os::is_headless_jre() { + struct stat statbuf; + char buf[MAXPATHLEN]; + char libmawtpath[MAXPATHLEN]; + const char *xawtstr = "/xawt/libmawt.so"; + const char *new_xawtstr = "/libawt_xawt.so"; + + char *p; + + // Get path to libjvm.so + os::jvm_path(buf, sizeof(buf)); + + // Get rid of libjvm.so + p = strrchr(buf, '/'); + if (p == NULL) return false; + else *p = '\0'; + + // Get rid of client or server + p = strrchr(buf, '/'); + if (p == NULL) return false; + else *p = '\0'; + + // check xawt/libmawt.so + strcpy(libmawtpath, buf); + strcat(libmawtpath, xawtstr); + if (::stat(libmawtpath, &statbuf) == 0) return false; + + // check libawt_xawt.so + strcpy(libmawtpath, buf); + strcat(libmawtpath, new_xawtstr); + if (::stat(libmawtpath, &statbuf) == 0) return false; + + return true; +} + +// Get the default path to the core file +// Returns the length of the string +int os::get_core_path(char* buffer, size_t bufferSize) { + const char* p = get_current_directory(buffer, bufferSize); + + if (p == NULL) { + assert(p != NULL, "failed to get current directory"); + return 0; + } + + return strlen(buffer); +} + +#ifndef PRODUCT +void TestReserveMemorySpecial_test() { + // No tests available for this platform +} +#endif diff --git a/hotspot/src/os/aix/vm/os_aix.hpp b/hotspot/src/os/aix/vm/os_aix.hpp new file mode 100644 index 00000000000..a7d2717c8e0 --- /dev/null +++ b/hotspot/src/os/aix/vm/os_aix.hpp @@ -0,0 +1,385 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_OS_AIX_HPP +#define OS_AIX_VM_OS_AIX_HPP + +// Information about the protection of the page at address '0' on this os. +static bool zero_page_read_protected() { return false; } + +// Class Aix defines the interface to the Aix operating systems. + +class Aix { + friend class os; + + // For signal-chaining + // highest so far (AIX 5.2) is SIGSAK (63) +#define MAXSIGNUM 63 + // length of strings included in the libperfstat structures +#define IDENTIFIER_LENGTH 64 + + static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions + static unsigned int sigs; // mask of signals that have + // preinstalled signal handlers + static bool libjsig_is_loaded; // libjsig that interposes sigaction(), + // __sigaction(), signal() is loaded + static struct sigaction *(*get_signal_action)(int); + static struct sigaction *get_preinstalled_handler(int); + static void save_preinstalled_handler(int, struct sigaction&); + + static void check_signal_handler(int sig); + + // For signal flags diagnostics + static int sigflags[MAXSIGNUM]; + + protected: + + static julong _physical_memory; + static pthread_t _main_thread; + static Mutex* _createThread_lock; + static int _page_size; + static int _logical_cpus; + + // -1 = uninitialized, 0 = AIX, 1 = OS/400 (PASE) + static int _on_pase; + + // -1 = uninitialized, otherwise 16 bit number: + // lower 8 bit - minor version + // higher 8 bit - major version + // For AIX, e.g. 0x0601 for AIX 6.1 + // for OS/400 e.g. 0x0504 for OS/400 V5R4 + static int _os_version; + + // -1 = uninitialized, + // 0 - SPEC1170 not requested (XPG_SUS_ENV is OFF or not set) + // 1 - SPEC1170 requested (XPG_SUS_ENV is ON) + static int _xpg_sus_mode; + + // -1 = uninitialized, + // 0 - EXTSHM=OFF or not set + // 1 - EXTSHM=ON + static int _extshm; + + // page sizes on AIX. + // + // AIX supports four different page sizes - 4K, 64K, 16MB, 16GB. The latter two + // (16M "large" resp. 16G "huge" pages) require special setup and are normally + // not available. + // + // AIX supports multiple page sizes per process, for: + // - Stack (of the primordial thread, so not relevant for us) + // - Data - data, bss, heap, for us also pthread stacks + // - Text - text code + // - shared memory + // + // Default page sizes can be set via linker options (-bdatapsize, -bstacksize, ...) + // and via environment variable LDR_CNTRL (DATAPSIZE, STACKPSIZE, ...) + // + // For shared memory, page size can be set dynamically via shmctl(). Different shared memory + // regions can have different page sizes. + // + // More information can be found at AIBM info center: + // http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/multiple_page_size_app_support.htm + // + // ----- + // We want to support 4K and 64K and, if the machine is set up correctly, 16MB pages. + // + + // page size of the stack of newly created pthreads + // (should be LDR_CNTRL DATAPSIZE because stack is allocated on heap by pthread lib) + static int _stack_page_size; + + // Default shm page size. Read: what page size shared memory will be backed + // with if no page size was set explicitly using shmctl(SHM_PAGESIZE). + // Should be LDR_CNTRL SHMPSIZE. + static size_t _shm_default_page_size; + + // True if sys V shm can be used with 64K pages dynamically. + // (via shmctl(.. SHM_PAGESIZE..). Should be true for AIX 53 and + // newer / PASE V6R1 and newer. (0 or 1, -1 if not initialized) + static int _can_use_64K_pages; + + // True if sys V shm can be used with 16M pages dynamically. + // (via shmctl(.. SHM_PAGESIZE..). Only true on AIX 5.3 and + // newer, if the system was set up to use 16M pages and the + // jvm has enough user rights. (0 or 1, -1 if not initialized) + static int _can_use_16M_pages; + + static julong available_memory(); + static julong physical_memory() { return _physical_memory; } + static void initialize_system_info(); + + // OS recognitions (PASE/AIX, OS level) call this before calling any + // one of Aix::on_pase(), Aix::os_version(). + static void initialize_os_info(); + + static int commit_memory_impl(char* addr, size_t bytes, bool exec); + static int commit_memory_impl(char* addr, size_t bytes, + size_t alignment_hint, bool exec); + + // Scan environment for important settings which might effect the + // VM. Trace out settings. Warn about invalid settings and/or + // correct them. + // + // Must run after os::Aix::initialue_os_info(). + static void scan_environment(); + + // Retrieve information about multipage size support. Will initialize + // _page_size, _stack_page_size, _can_use_64K_pages/_can_use_16M_pages + static void query_multipage_support(); + + // Initialize libo4 (on PASE) and libperfstat (on AIX). Call this + // before relying on functions from either lib, e.g. Aix::get_meminfo(). + static void initialize_libo4(); + static void initialize_libperfstat(); + + static bool supports_variable_stack_size(); + + public: + static void init_thread_fpu_state(); + static pthread_t main_thread(void) { return _main_thread; } + // returns kernel thread id (similar to LWP id on Solaris), which can be + // used to access /proc + static pid_t gettid(); + static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; } + static Mutex* createThread_lock(void) { return _createThread_lock; } + static void hotspot_sigmask(Thread* thread); + + // Given an address, returns the size of the page backing that address + static size_t query_pagesize(void* p); + + // Return `true' if the calling thread is the primordial thread. The + // primordial thread is the thread which contains the main function, + // *not* necessarily the thread which initialized the VM by calling + // JNI_CreateJavaVM. + static bool is_primordial_thread(void); + + static int page_size(void) { + assert(_page_size != -1, "not initialized"); + return _page_size; + } + + // Accessor methods for stack page size which may be different from usual page size. + static int stack_page_size(void) { + assert(_stack_page_size != -1, "not initialized"); + return _stack_page_size; + } + + // default shm page size. Read: what page size shared memory + // will be backed with if no page size was set explicitly using shmctl(SHM_PAGESIZE). + // Should be LDR_CNTRL SHMPSIZE. + static int shm_default_page_size(void) { + assert(_shm_default_page_size != -1, "not initialized"); + return _shm_default_page_size; + } + + // Return true if sys V shm can be used with 64K pages dynamically + // (via shmctl(.. SHM_PAGESIZE..). + static bool can_use_64K_pages () { + assert(_can_use_64K_pages != -1, "not initialized"); + return _can_use_64K_pages == 1 ? true : false; + } + + // Return true if sys V shm can be used with 16M pages dynamically. + // (via shmctl(.. SHM_PAGESIZE..). + static bool can_use_16M_pages () { + assert(_can_use_16M_pages != -1, "not initialized"); + return _can_use_16M_pages == 1 ? true : false; + } + + static address ucontext_get_pc(ucontext_t* uc); + static intptr_t* ucontext_get_sp(ucontext_t* uc); + static intptr_t* ucontext_get_fp(ucontext_t* uc); + // Set PC into context. Needed for continuation after signal. + static void ucontext_set_pc(ucontext_t* uc, address pc); + + // This boolean allows users to forward their own non-matching signals + // to JVM_handle_aix_signal, harmlessly. + static bool signal_handlers_are_installed; + + static int get_our_sigflags(int); + static void set_our_sigflags(int, int); + static void signal_sets_init(); + static void install_signal_handlers(); + static void set_signal_handler(int, bool); + static bool is_sig_ignored(int sig); + + static sigset_t* unblocked_signals(); + static sigset_t* vm_signals(); + static sigset_t* allowdebug_blocked_signals(); + + // For signal-chaining + static struct sigaction *get_chained_signal_action(int sig); + static bool chained_handler(int sig, siginfo_t* siginfo, void* context); + + // libpthread version string + static void libpthread_init(); + + // Minimum stack size a thread can be created with (allowing + // the VM to completely create the thread and enter user code) + static size_t min_stack_allowed; + + // Return default stack size or guard size for the specified thread type + static size_t default_stack_size(os::ThreadType thr_type); + static size_t default_guard_size(os::ThreadType thr_type); + + // Function returns true if we run on OS/400 (pase), false if we run + // on AIX. + static bool on_pase() { + assert(_on_pase != -1, "not initialized"); + return _on_pase ? true : false; + } + + // Function returns true if we run on AIX, false if we run on OS/400 + // (pase). + static bool on_aix() { + assert(_on_pase != -1, "not initialized"); + return _on_pase ? false : true; + } + + // -1 = uninitialized, otherwise 16 bit number: + // lower 8 bit - minor version + // higher 8 bit - major version + // For AIX, e.g. 0x0601 for AIX 6.1 + // for OS/400 e.g. 0x0504 for OS/400 V5R4 + static int os_version () { + assert(_os_version != -1, "not initialized"); + return _os_version; + } + + // Convenience method: returns true if running on AIX 5.3 or older. + static bool on_aix_53_or_older() { + return on_aix() && os_version() <= 0x0503; + } + + // Returns true if we run in SPEC1170 compliant mode (XPG_SUS_ENV=ON). + static bool xpg_sus_mode() { + assert(_xpg_sus_mode != -1, "not initialized"); + return _xpg_sus_mode; + } + + // Returns true if EXTSHM=ON. + static bool extshm() { + assert(_extshm != -1, "not initialized"); + return _extshm; + } + + // result struct for get_meminfo() + struct meminfo_t { + + // Amount of virtual memory (in units of 4 KB pages) + unsigned long long virt_total; + + // Amount of real memory, in bytes + unsigned long long real_total; + + // Amount of free real memory, in bytes + unsigned long long real_free; + + // Total amount of paging space, in bytes + unsigned long long pgsp_total; + + // Amount of free paging space, in bytes + unsigned long long pgsp_free; + + }; + + // Result struct for get_cpuinfo(). + struct cpuinfo_t { + char description[IDENTIFIER_LENGTH]; // processor description (type/official name) + u_longlong_t processorHZ; // processor speed in Hz + int ncpus; // number of active logical processors + double loadavg[3]; // (1<. + char version[20]; // processor version from _system_configuration (sys/systemcfg.h) + }; + + // Functions to retrieve memory information on AIX, PASE. + // (on AIX, using libperfstat, on PASE with libo4.so). + // Returns true if ok, false if error. + static bool get_meminfo(meminfo_t* pmi); + + // Function to retrieve cpu information on AIX + // (on AIX, using libperfstat) + // Returns true if ok, false if error. + static bool get_cpuinfo(cpuinfo_t* pci); + +}; // os::Aix class + + +class PlatformEvent : public CHeapObj { + private: + double CachePad [4]; // increase odds that _mutex is sole occupant of cache line + volatile int _Event; + volatile int _nParked; + pthread_mutex_t _mutex [1]; + pthread_cond_t _cond [1]; + double PostPad [2]; + Thread * _Assoc; + + public: // TODO-FIXME: make dtor private + ~PlatformEvent() { guarantee (0, "invariant"); } + + public: + PlatformEvent() { + int status; + status = pthread_cond_init (_cond, NULL); + assert_status(status == 0, status, "cond_init"); + status = pthread_mutex_init (_mutex, NULL); + assert_status(status == 0, status, "mutex_init"); + _Event = 0; + _nParked = 0; + _Assoc = NULL; + } + + // Use caution with reset() and fired() -- they may require MEMBARs + void reset() { _Event = 0; } + int fired() { return _Event; } + void park (); + void unpark (); + int TryPark (); + int park (jlong millis); + void SetAssociation (Thread * a) { _Assoc = a; } +}; + +class PlatformParker : public CHeapObj { + protected: + pthread_mutex_t _mutex [1]; + pthread_cond_t _cond [1]; + + public: // TODO-FIXME: make dtor private + ~PlatformParker() { guarantee (0, "invariant"); } + + public: + PlatformParker() { + int status; + status = pthread_cond_init (_cond, NULL); + assert_status(status == 0, status, "cond_init"); + status = pthread_mutex_init (_mutex, NULL); + assert_status(status == 0, status, "mutex_init"); + } +}; + +#endif // OS_AIX_VM_OS_AIX_HPP diff --git a/hotspot/src/os/aix/vm/os_aix.inline.hpp b/hotspot/src/os/aix/vm/os_aix.inline.hpp new file mode 100644 index 00000000000..ff9c7a7aa3e --- /dev/null +++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_OS_AIX_INLINE_HPP +#define OS_AIX_VM_OS_AIX_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#ifdef TARGET_OS_ARCH_aix_ppc +# include "atomic_aix_ppc.inline.hpp" +# include "orderAccess_aix_ppc.inline.hpp" +#endif + +// System includes + +#include +#include +#include +#include +#include + +// Defined in the system headers included above. +#undef rem_size + +inline void* os::thread_local_storage_at(int index) { + return pthread_getspecific((pthread_key_t)index); +} + +inline const char* os::file_separator() { + return "/"; +} + +inline const char* os::line_separator() { + return "\n"; +} + +inline const char* os::path_separator() { + return ":"; +} + +// File names are case-sensitive on windows only +inline int os::file_name_strcmp(const char* s1, const char* s2) { + return strcmp(s1, s2); +} + +inline bool os::obsolete_option(const JavaVMOption *option) { + return false; +} + +inline bool os::uses_stack_guard_pages() { + return true; +} + +inline bool os::allocate_stack_guard_pages() { + assert(uses_stack_guard_pages(), "sanity check"); + return true; +} + + +// On Aix, reservations are made on a page by page basis, nothing to do. +inline void os::pd_split_reserved_memory(char *base, size_t size, + size_t split, bool realloc) { +} + + +// Bang the shadow pages if they need to be touched to be mapped. +inline void os::bang_stack_shadow_pages() { +} + +inline void os::dll_unload(void *lib) { + ::dlclose(lib); +} + +inline const int os::default_file_open_flags() { return 0;} + +inline DIR* os::opendir(const char* dirname) +{ + assert(dirname != NULL, "just checking"); + return ::opendir(dirname); +} + +inline int os::readdir_buf_size(const char *path) +{ + // according to aix sys/limits, NAME_MAX must be retrieved at runtime. */ + const long my_NAME_MAX = pathconf(path, _PC_NAME_MAX); + return my_NAME_MAX + sizeof(dirent) + 1; +} + +inline jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::lseek64(fd, offset, whence); +} + +inline int os::fsync(int fd) { + return ::fsync(fd); +} + +inline char* os::native_path(char *path) { + return path; +} + +inline int os::ftruncate(int fd, jlong length) { + return ::ftruncate64(fd, length); +} + +inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf) +{ + dirent* p; + int status; + assert(dirp != NULL, "just checking"); + + // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX + // version. Here is the doc for this function: + // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html + + if((status = ::readdir_r(dirp, dbuf, &p)) != 0) { + errno = status; + return NULL; + } else + return p; +} + +inline int os::closedir(DIR *dirp) { + assert(dirp != NULL, "argument is NULL"); + return ::closedir(dirp); +} + +// macros for restartable system calls + +#define RESTARTABLE(_cmd, _result) do { \ + _result = _cmd; \ + } while(((int)_result == OS_ERR) && (errno == EINTR)) + +#define RESTARTABLE_RETURN_INT(_cmd) do { \ + int _result; \ + RESTARTABLE(_cmd, _result); \ + return _result; \ +} while(false) + +// We don't have NUMA support on Aix, but we need this for compilation. +inline bool os::numa_has_static_binding() { ShouldNotReachHere(); return true; } +inline bool os::numa_has_group_homing() { ShouldNotReachHere(); return false; } + +inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res); + return res; +} + +inline size_t os::write(int fd, const void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); + return res; +} + +inline int os::close(int fd) { + return ::close(fd); +} + +inline int os::socket_close(int fd) { + return ::close(fd); +} + +inline int os::socket(int domain, int type, int protocol) { + return ::socket(domain, type, protocol); +} + +inline int os::recv(int fd, char* buf, size_t nBytes, uint flags) { + RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, flags)); +} + +inline int os::send(int fd, char* buf, size_t nBytes, uint flags) { + RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags)); +} + +inline int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) { + return os::send(fd, buf, nBytes, flags); +} + +inline int os::timeout(int fd, long timeout) { + julong prevtime,newtime; + struct timeval t; + + gettimeofday(&t, NULL); + prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + struct pollfd pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = ::poll(&pfd, 1, timeout); + + if (res == OS_ERR && errno == EINTR) { + + // On Linux any value < 0 means "forever" + + if(timeout >= 0) { + gettimeofday(&t, NULL); + newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } +} + +inline int os::listen(int fd, int count) { + return ::listen(fd, count); +} + +inline int os::connect(int fd, struct sockaddr* him, socklen_t len) { + RESTARTABLE_RETURN_INT(::connect(fd, him, len)); +} + +inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) { + // Linux doc says this can't return EINTR, unlike accept() on Solaris. + // But see attachListener_linux.cpp, LinuxAttachListener::dequeue(). + return (int)::accept(fd, him, len); +} + +inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags, + sockaddr* from, socklen_t* fromlen) { + RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen)); +} + +inline int os::sendto(int fd, char* buf, size_t len, uint flags, + struct sockaddr* to, socklen_t tolen) { + RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen)); +} + +inline int os::socket_shutdown(int fd, int howto) { + return ::shutdown(fd, howto); +} + +inline int os::bind(int fd, struct sockaddr* him, socklen_t len) { + return ::bind(fd, him, len); +} + +inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) { + return ::getsockname(fd, him, len); +} + +inline int os::get_host_name(char* name, int namelen) { + return ::gethostname(name, namelen); +} + +inline struct hostent* os::get_host_by_name(char* name) { + return ::gethostbyname(name); +} + +inline int os::get_sock_opt(int fd, int level, int optname, + char* optval, socklen_t* optlen) { + return ::getsockopt(fd, level, optname, optval, optlen); +} + +inline int os::set_sock_opt(int fd, int level, int optname, + const char* optval, socklen_t optlen) { + return ::setsockopt(fd, level, optname, optval, optlen); +} +#endif // OS_AIX_VM_OS_AIX_INLINE_HPP diff --git a/hotspot/src/os/aix/vm/os_share_aix.hpp b/hotspot/src/os/aix/vm/os_share_aix.hpp new file mode 100644 index 00000000000..dc6c9871f1c --- /dev/null +++ b/hotspot/src/os/aix/vm/os_share_aix.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_OS_SHARE_AIX_HPP +#define OS_AIX_VM_OS_SHARE_AIX_HPP + +// misc +void signalHandler(int, siginfo_t*, ucontext_t*); +void handle_unexpected_exception(Thread* thread, int sig, siginfo_t* info, address pc, address adjusted_pc); +#ifndef PRODUCT +void continue_with_dump(void); +#endif + +#define PROCFILE_LENGTH 128 + +#endif // OS_AIX_VM_OS_SHARE_AIX_HPP diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp new file mode 100644 index 00000000000..a30919c70df --- /dev/null +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -0,0 +1,1026 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/vmSymbols.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" +#include "oops/oop.inline.hpp" +#include "os_aix.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/perfMemory.hpp" +#include "utilities/exceptions.hpp" + +// put OS-includes here +# include +# include +# include +# include +# include +# include +# include +# include + +static char* backing_store_file_name = NULL; // name of the backing store + // file, if successfully created. + +// Standard Memory Implementation Details + +// create the PerfData memory region in standard memory. +// +static char* create_standard_memory(size_t size) { + + // allocate an aligned chuck of memory + char* mapAddress = os::reserve_memory(size); + + if (mapAddress == NULL) { + return NULL; + } + + // commit memory + if (!os::commit_memory(mapAddress, size, !ExecMem)) { + if (PrintMiscellaneous && Verbose) { + warning("Could not commit PerfData memory\n"); + } + os::release_memory(mapAddress, size); + return NULL; + } + + return mapAddress; +} + +// delete the PerfData memory region +// +static void delete_standard_memory(char* addr, size_t size) { + + // there are no persistent external resources to cleanup for standard + // memory. since DestroyJavaVM does not support unloading of the JVM, + // cleanup of the memory resource is not performed. The memory will be + // reclaimed by the OS upon termination of the process. + // + return; +} + +// save the specified memory region to the given file +// +// Note: this function might be called from signal handler (by os::abort()), +// don't allocate heap memory. +// +static void save_memory_to_file(char* addr, size_t size) { + + const char* destfile = PerfMemory::get_perfdata_file_path(); + assert(destfile[0] != '\0', "invalid PerfData file path"); + + int result; + + RESTARTABLE(::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE), + result);; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("Could not create Perfdata save file: %s: %s\n", + destfile, strerror(errno)); + } + } else { + int fd = result; + + for (size_t remaining = size; remaining > 0;) { + + RESTARTABLE(::write(fd, addr, remaining), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("Could not write Perfdata save file: %s: %s\n", + destfile, strerror(errno)); + } + break; + } + + remaining -= (size_t)result; + addr += result; + } + + RESTARTABLE(::close(fd), result); + if (PrintMiscellaneous && Verbose) { + if (result == OS_ERR) { + warning("Could not close %s: %s\n", destfile, strerror(errno)); + } + } + } + FREE_C_HEAP_ARRAY(char, destfile, mtInternal); +} + + +// Shared Memory Implementation Details + +// Note: the solaris and linux shared memory implementation uses the mmap +// interface with a backing store file to implement named shared memory. +// Using the file system as the name space for shared memory allows a +// common name space to be supported across a variety of platforms. It +// also provides a name space that Java applications can deal with through +// simple file apis. +// +// The solaris and linux implementations store the backing store file in +// a user specific temporary directory located in the /tmp file system, +// which is always a local file system and is sometimes a RAM based file +// system. + +// return the user specific temporary directory name. +// +// the caller is expected to free the allocated memory. +// +static char* get_user_tmp_dir(const char* user) { + + const char* tmpdir = os::get_temp_directory(); + const char* perfdir = PERFDATA_NAME; + size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3; + char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); + + // construct the path name to user specific tmp directory + snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user); + + return dirname; +} + +// convert the given file name into a process id. if the file +// does not meet the file naming constraints, return 0. +// +static pid_t filename_to_pid(const char* filename) { + + // a filename that doesn't begin with a digit is not a + // candidate for conversion. + // + if (!isdigit(*filename)) { + return 0; + } + + // check if file name can be converted to an integer without + // any leftover characters. + // + char* remainder = NULL; + errno = 0; + pid_t pid = (pid_t)strtol(filename, &remainder, 10); + + if (errno != 0) { + return 0; + } + + // check for left over characters. If any, then the filename is + // not a candidate for conversion. + // + if (remainder != NULL && *remainder != '\0') { + return 0; + } + + // successful conversion, return the pid + return pid; +} + + +// check if the given path is considered a secure directory for +// the backing store files. Returns true if the directory exists +// and is considered a secure location. Returns false if the path +// is a symbolic link or if an error occurred. +// +static bool is_directory_secure(const char* path) { + struct stat statbuf; + int result = 0; + + RESTARTABLE(::lstat(path, &statbuf), result); + if (result == OS_ERR) { + return false; + } + + // the path exists, now check it's mode + if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { + // the path represents a link or some non-directory file type, + // which is not what we expected. declare it insecure. + // + return false; + } + else { + // we have an existing directory, check if the permissions are safe. + // + if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { + // the directory is open for writing and could be subjected + // to a symlnk attack. declare it insecure. + // + return false; + } + } + return true; +} + + +// return the user name for the given user id +// +// the caller is expected to free the allocated memory. +// +static char* get_user_name(uid_t uid) { + + struct passwd pwent; + + // determine the max pwbuf size from sysconf, and hardcode + // a default if this not available through sysconf. + // + long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal); + + // POSIX interface to getpwuid_r is used on LINUX + struct passwd* p; + int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p); + + if (result != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + if (PrintMiscellaneous && Verbose) { + if (result != 0) { + warning("Could not retrieve passwd entry: %s\n", + strerror(result)); + } + else if (p == NULL) { + // this check is added to protect against an observed problem + // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0, + // indicating success, but has p == NULL. This was observed when + // inserting a file descriptor exhaustion fault prior to the call + // getpwuid_r() call. In this case, error is set to the appropriate + // error condition, but this is undocumented behavior. This check + // is safe under any condition, but the use of errno in the output + // message may result in an erroneous message. + // Bug Id 89052 was opened with RedHat. + // + warning("Could not retrieve passwd entry: %s\n", + strerror(errno)); + } + else { + warning("Could not determine user name: %s\n", + p->pw_name == NULL ? "pw_name = NULL" : + "pw_name zero length"); + } + } + FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal); + return NULL; + } + + char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal); + strcpy(user_name, p->pw_name); + + FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal); + return user_name; +} + +// return the name of the user that owns the process identified by vmid. +// +// This method uses a slow directory search algorithm to find the backing +// store file for the specified vmid and returns the user name, as determined +// by the user name suffix of the hsperfdata_ directory name. +// +// the caller is expected to free the allocated memory. +// +static char* get_user_name_slow(int vmid, TRAPS) { + + // short circuit the directory search if the process doesn't even exist. + if (kill(vmid, 0) == OS_ERR) { + if (errno == ESRCH) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + else /* EPERM */ { + THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + } + } + + // directory search + char* oldest_user = NULL; + time_t oldest_ctime = 0; + + const char* tmpdirname = os::get_temp_directory(); + + DIR* tmpdirp = os::opendir(tmpdirname); + + if (tmpdirp == NULL) { + return NULL; + } + + // for each entry in the directory that matches the pattern hsperfdata_*, + // open the directory and check if the file for the given vmid exists. + // The file with the expected name and the latest creation date is used + // to determine the user name for the process id. + // + struct dirent* dentry; + char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal); + errno = 0; + while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) { + + // check if the directory entry is a hsperfdata file + if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) { + continue; + } + + char* usrdir_name = NEW_C_HEAP_ARRAY(char, + strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); + strcpy(usrdir_name, tmpdirname); + strcat(usrdir_name, "/"); + strcat(usrdir_name, dentry->d_name); + + DIR* subdirp = os::opendir(usrdir_name); + + if (subdirp == NULL) { + FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); + continue; + } + + // Since we don't create the backing store files in directories + // pointed to by symbolic links, we also don't follow them when + // looking for the files. We check for a symbolic link after the + // call to opendir in order to eliminate a small window where the + // symlink can be exploited. + // + if (!is_directory_secure(usrdir_name)) { + FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); + os::closedir(subdirp); + continue; + } + + struct dirent* udentry; + char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); + errno = 0; + while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) { + + if (filename_to_pid(udentry->d_name) == vmid) { + struct stat statbuf; + int result; + + char* filename = NEW_C_HEAP_ARRAY(char, + strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal); + + strcpy(filename, usrdir_name); + strcat(filename, "/"); + strcat(filename, udentry->d_name); + + // don't follow symbolic links for the file + RESTARTABLE(::lstat(filename, &statbuf), result); + if (result == OS_ERR) { + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + continue; + } + + // skip over files that are not regular files. + if (!S_ISREG(statbuf.st_mode)) { + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + continue; + } + + // compare and save filename with latest creation time + if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) { + + if (statbuf.st_ctime > oldest_ctime) { + char* user = strchr(dentry->d_name, '_') + 1; + + if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal); + oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal); + + strcpy(oldest_user, user); + oldest_ctime = statbuf.st_ctime; + } + } + + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + } + } + os::closedir(subdirp); + FREE_C_HEAP_ARRAY(char, udbuf, mtInternal); + FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); + } + os::closedir(tmpdirp); + FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal); + + return(oldest_user); +} + +// return the name of the user that owns the JVM indicated by the given vmid. +// +static char* get_user_name(int vmid, TRAPS) { + return get_user_name_slow(vmid, CHECK_NULL); +} + +// return the file name of the backing store file for the named +// shared memory region for the given user name and vmid. +// +// the caller is expected to free the allocated memory. +// +static char* get_sharedmem_filename(const char* dirname, int vmid) { + + // add 2 for the file separator and a null terminator. + size_t nbytes = strlen(dirname) + UINT_CHARS + 2; + + char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); + snprintf(name, nbytes, "%s/%d", dirname, vmid); + + return name; +} + + +// remove file +// +// this method removes the file specified by the given path +// +static void remove_file(const char* path) { + + int result; + + // if the file is a directory, the following unlink will fail. since + // we don't expect to find directories in the user temp directory, we + // won't try to handle this situation. even if accidentially or + // maliciously planted, the directory's presence won't hurt anything. + // + RESTARTABLE(::unlink(path), result); + if (PrintMiscellaneous && Verbose && result == OS_ERR) { + if (errno != ENOENT) { + warning("Could not unlink shared memory backing" + " store file %s : %s\n", path, strerror(errno)); + } + } +} + + +// remove file +// +// this method removes the file with the given file name in the +// named directory. +// +static void remove_file(const char* dirname, const char* filename) { + + size_t nbytes = strlen(dirname) + strlen(filename) + 2; + char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); + + strcpy(path, dirname); + strcat(path, "/"); + strcat(path, filename); + + remove_file(path); + + FREE_C_HEAP_ARRAY(char, path, mtInternal); +} + + +// cleanup stale shared memory resources +// +// This method attempts to remove all stale shared memory files in +// the named user temporary directory. It scans the named directory +// for files matching the pattern ^$[0-9]*$. For each file found, the +// process id is extracted from the file name and a test is run to +// determine if the process is alive. If the process is not alive, +// any stale file resources are removed. +// +static void cleanup_sharedmem_resources(const char* dirname) { + + // open the user temp directory + DIR* dirp = os::opendir(dirname); + + if (dirp == NULL) { + // directory doesn't exist, so there is nothing to cleanup + return; + } + + if (!is_directory_secure(dirname)) { + // the directory is not a secure directory + return; + } + + // for each entry in the directory that matches the expected file + // name pattern, determine if the file resources are stale and if + // so, remove the file resources. Note, instrumented HotSpot processes + // for this user may start and/or terminate during this search and + // remove or create new files in this directory. The behavior of this + // loop under these conditions is dependent upon the implementation of + // opendir/readdir. + // + struct dirent* entry; + char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); + errno = 0; + while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { + + pid_t pid = filename_to_pid(entry->d_name); + + if (pid == 0) { + + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + + // attempt to remove all unexpected files, except "." and ".." + remove_file(dirname, entry->d_name); + } + + errno = 0; + continue; + } + + // we now have a file name that converts to a valid integer + // that could represent a process id . if this process id + // matches the current process id or the process is not running, + // then remove the stale file resources. + // + // process liveness is detected by sending signal number 0 to + // the process id (see kill(2)). if kill determines that the + // process does not exist, then the file resources are removed. + // if kill determines that that we don't have permission to + // signal the process, then the file resources are assumed to + // be stale and are removed because the resources for such a + // process should be in a different user specific directory. + // + if ((pid == os::current_process_id()) || + (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { + + remove_file(dirname, entry->d_name); + } + errno = 0; + } + os::closedir(dirp); + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); +} + +// make the user specific temporary directory. Returns true if +// the directory exists and is secure upon return. Returns false +// if the directory exists but is either a symlink, is otherwise +// insecure, or if an error occurred. +// +static bool make_user_tmp_dir(const char* dirname) { + + // create the directory with 0755 permissions. note that the directory + // will be owned by euid::egid, which may not be the same as uid::gid. + // + if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) { + if (errno == EEXIST) { + // The directory already exists and was probably created by another + // JVM instance. However, this could also be the result of a + // deliberate symlink. Verify that the existing directory is safe. + // + if (!is_directory_secure(dirname)) { + // directory is not secure + if (PrintMiscellaneous && Verbose) { + warning("%s directory is insecure\n", dirname); + } + return false; + } + } + else { + // we encountered some other failure while attempting + // to create the directory + // + if (PrintMiscellaneous && Verbose) { + warning("could not create directory %s: %s\n", + dirname, strerror(errno)); + } + return false; + } + } + return true; +} + +// create the shared memory file resources +// +// This method creates the shared memory file with the given size +// This method also creates the user specific temporary directory, if +// it does not yet exist. +// +static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) { + + // make the user temporary directory + if (!make_user_tmp_dir(dirname)) { + // could not make/find the directory or the found directory + // was not secure + return -1; + } + + int result; + + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not create file %s: %s\n", filename, strerror(errno)); + } + return -1; + } + + // save the file descriptor + int fd = result; + + // set the file size + RESTARTABLE(::ftruncate(fd, (off_t)size), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not set shared memory file size: %s\n", strerror(errno)); + } + RESTARTABLE(::close(fd), result); + return -1; + } + + return fd; +} + +// open the shared memory file for the given user and vmid. returns +// the file descriptor for the open file or -1 if the file could not +// be opened. +// +static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { + + // open the file + int result; + RESTARTABLE(::open(filename, oflags), result); + if (result == OS_ERR) { + if (errno == ENOENT) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + else if (errno == EACCES) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Permission denied"); + } + else { + THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + } + } + + return result; +} + +// create a named shared memory region. returns the address of the +// memory region on success or NULL on failure. A return value of +// NULL will ultimately disable the shared memory feature. +// +// On Solaris and Linux, the name space for shared memory objects +// is the file system name space. +// +// A monitoring application attaching to a JVM does not need to know +// the file system name of the shared memory object. However, it may +// be convenient for applications to discover the existence of newly +// created and terminating JVMs by watching the file system name space +// for files being created or removed. +// +static char* mmap_create_shared(size_t size) { + + int result; + int fd; + char* mapAddress; + + int vmid = os::current_process_id(); + + char* user_name = get_user_name(geteuid()); + + if (user_name == NULL) + return NULL; + + char* dirname = get_user_tmp_dir(user_name); + char* filename = get_sharedmem_filename(dirname, vmid); + + // cleanup any stale shared memory files + cleanup_sharedmem_resources(dirname); + + assert(((size > 0) && (size % os::vm_page_size() == 0)), + "unexpected PerfMemory region size"); + + fd = create_sharedmem_resources(dirname, filename, size); + + FREE_C_HEAP_ARRAY(char, user_name, mtInternal); + FREE_C_HEAP_ARRAY(char, dirname, mtInternal); + + if (fd == -1) { + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + return NULL; + } + + mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + + // attempt to close the file - restart it if it was interrupted, + // but ignore other failures + RESTARTABLE(::close(fd), result); + assert(result != OS_ERR, "could not close file"); + + if (mapAddress == MAP_FAILED) { + if (PrintMiscellaneous && Verbose) { + warning("mmap failed - %s\n", strerror(errno)); + } + remove_file(filename); + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + return NULL; + } + + // save the file name for use in delete_shared_memory() + backing_store_file_name = filename; + + // clear the shared memory region + (void)::memset((void*) mapAddress, 0, size); + + return mapAddress; +} + +// release a named shared memory region +// +static void unmap_shared(char* addr, size_t bytes) { + // Do not rely on os::reserve_memory/os::release_memory to use mmap. + // Use os::reserve_memory/os::release_memory for PerfDisableSharedMem=1, mmap/munmap for PerfDisableSharedMem=0 + if (::munmap(addr, bytes) == -1) { + warning("perfmemory: munmap failed (%d)\n", errno); + } +} + +// create the PerfData memory region in shared memory. +// +static char* create_shared_memory(size_t size) { + + // create the shared memory region. + return mmap_create_shared(size); +} + +// delete the shared PerfData memory region +// +static void delete_shared_memory(char* addr, size_t size) { + + // cleanup the persistent shared memory resources. since DestroyJavaVM does + // not support unloading of the JVM, unmapping of the memory resource is + // not performed. The memory will be reclaimed by the OS upon termination of + // the process. The backing store file is deleted from the file system. + + assert(!PerfDisableSharedMem, "shouldn't be here"); + + if (backing_store_file_name != NULL) { + remove_file(backing_store_file_name); + // Don't.. Free heap memory could deadlock os::abort() if it is called + // from signal handler. OS will reclaim the heap memory. + // FREE_C_HEAP_ARRAY(char, backing_store_file_name, mtInternal); + backing_store_file_name = NULL; + } +} + +// return the size of the file for the given file descriptor +// or 0 if it is not a valid size for a shared memory file +// +static size_t sharedmem_filesize(int fd, TRAPS) { + + struct stat statbuf; + int result; + + RESTARTABLE(::fstat(fd, &statbuf), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("fstat failed: %s\n", strerror(errno)); + } + THROW_MSG_0(vmSymbols::java_io_IOException(), + "Could not determine PerfMemory size"); + } + + if ((statbuf.st_size == 0) || + ((size_t)statbuf.st_size % os::vm_page_size() != 0)) { + THROW_MSG_0(vmSymbols::java_lang_Exception(), + "Invalid PerfMemory size"); + } + + return (size_t)statbuf.st_size; +} + +// attach to a named shared memory region. +// +static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) { + + char* mapAddress; + int result; + int fd; + size_t size; + const char* luser = NULL; + + int mmap_prot; + int file_flags; + + ResourceMark rm; + + // map the high level access mode to the appropriate permission + // constructs for the file and the shared memory mapping. + if (mode == PerfMemory::PERF_MODE_RO) { + mmap_prot = PROT_READ; + file_flags = O_RDONLY; + } + else if (mode == PerfMemory::PERF_MODE_RW) { +#ifdef LATER + mmap_prot = PROT_READ | PROT_WRITE; + file_flags = O_RDWR; +#else + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Unsupported access mode"); +#endif + } + else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Illegal access mode"); + } + + if (user == NULL || strlen(user) == 0) { + luser = get_user_name(vmid, CHECK); + } + else { + luser = user; + } + + if (luser == NULL) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Could not map vmid to user Name"); + } + + char* dirname = get_user_tmp_dir(luser); + + // since we don't follow symbolic links when creating the backing + // store file, we don't follow them when attaching either. + // + if (!is_directory_secure(dirname)) { + FREE_C_HEAP_ARRAY(char, dirname, mtInternal); + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + + char* filename = get_sharedmem_filename(dirname, vmid); + + // copy heap memory to resource memory. the open_sharedmem_file + // method below need to use the filename, but could throw an + // exception. using a resource array prevents the leak that + // would otherwise occur. + char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1); + strcpy(rfilename, filename); + + // free the c heap resources that are no longer needed + if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal); + FREE_C_HEAP_ARRAY(char, dirname, mtInternal); + FREE_C_HEAP_ARRAY(char, filename, mtInternal); + + // open the shared memory file for the give vmid + fd = open_sharedmem_file(rfilename, file_flags, CHECK); + assert(fd != OS_ERR, "unexpected value"); + + if (*sizep == 0) { + size = sharedmem_filesize(fd, CHECK); + assert(size != 0, "unexpected size"); + } else { + size = *sizep; + } + + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); + + // attempt to close the file - restart if it gets interrupted, + // but ignore other failures + RESTARTABLE(::close(fd), result); + assert(result != OS_ERR, "could not close file"); + + if (mapAddress == MAP_FAILED) { + if (PrintMiscellaneous && Verbose) { + warning("mmap failed: %s\n", strerror(errno)); + } + THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), + "Could not map PerfMemory"); + } + + *addr = mapAddress; + *sizep = size; + + if (PerfTraceMemOps) { + tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " + INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress); + } +} + + + + +// create the PerfData memory region +// +// This method creates the memory region used to store performance +// data for the JVM. The memory may be created in standard or +// shared memory. +// +void PerfMemory::create_memory_region(size_t size) { + + if (PerfDisableSharedMem) { + // do not share the memory for the performance data. + _start = create_standard_memory(size); + } + else { + _start = create_shared_memory(size); + if (_start == NULL) { + + // creation of the shared memory region failed, attempt + // to create a contiguous, non-shared memory region instead. + // + if (PrintMiscellaneous && Verbose) { + warning("Reverting to non-shared PerfMemory region.\n"); + } + PerfDisableSharedMem = true; + _start = create_standard_memory(size); + } + } + + if (_start != NULL) _capacity = size; + +} + +// delete the PerfData memory region +// +// This method deletes the memory region used to store performance +// data for the JVM. The memory region indicated by the +// tuple will be inaccessible after a call to this method. +// +void PerfMemory::delete_memory_region() { + + assert((start() != NULL && capacity() > 0), "verify proper state"); + + // If user specifies PerfDataSaveFile, it will save the performance data + // to the specified file name no matter whether PerfDataSaveToFile is specified + // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag + // -XX:+PerfDataSaveToFile. + if (PerfDataSaveToFile || PerfDataSaveFile != NULL) { + save_memory_to_file(start(), capacity()); + } + + if (PerfDisableSharedMem) { + delete_standard_memory(start(), capacity()); + } + else { + delete_shared_memory(start(), capacity()); + } +} + +// attach to the PerfData memory region for another JVM +// +// This method returns an tuple that points to +// a memory buffer that is kept reasonably synchronized with +// the PerfData memory region for the indicated JVM. This +// buffer may be kept in synchronization via shared memory +// or some other mechanism that keeps the buffer updated. +// +// If the JVM chooses not to support the attachability feature, +// this method should throw an UnsupportedOperation exception. +// +// This implementation utilizes named shared memory to map +// the indicated process's PerfData memory region into this JVMs +// address space. +// +void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPS) { + + if (vmid == 0 || vmid == os::current_process_id()) { + *addrp = start(); + *sizep = capacity(); + return; + } + + mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK); +} + +// detach from the PerfData memory region of another JVM +// +// This method detaches the PerfData memory region of another +// JVM, specified as an tuple of a buffer +// in this process's address space. This method may perform +// arbitrary actions to accomplish the detachment. The memory +// region specified by will be inaccessible after +// a call to this method. +// +// If the JVM chooses not to support the attachability feature, +// this method should throw an UnsupportedOperation exception. +// +// This implementation utilizes named shared memory to detach +// the indicated process's PerfData memory region from this +// process's address space. +// +void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { + + assert(addr != 0, "address sanity check"); + assert(bytes > 0, "capacity sanity check"); + + if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) { + // prevent accidental detachment of this process's PerfMemory region + return; + } + + unmap_shared(addr, bytes); +} + +char* PerfMemory::backing_store_filename() { + return backing_store_file_name; +} diff --git a/hotspot/src/os/aix/vm/porting_aix.cpp b/hotspot/src/os/aix/vm/porting_aix.cpp new file mode 100644 index 00000000000..b79d33d742c --- /dev/null +++ b/hotspot/src/os/aix/vm/porting_aix.cpp @@ -0,0 +1,367 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "asm/assembler.hpp" +#include "loadlib_aix.hpp" +#include "porting_aix.hpp" +#include "utilities/debug.hpp" + +#include +#include + +////////////////////////////////// +// Provide implementation for dladdr based on LoadedLibraries pool and +// traceback table scan (see getFuncName). + +// Search traceback table in stack, +// return procedure name from trace back table. +#define MAX_FUNC_SEARCH_LEN 0x10000 +// Any PC below this value is considered toast. +#define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024) + +#define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2)) + +// Align a pointer without having to cast. +inline char* align_ptr_up(char* ptr, intptr_t alignment) { + return (char*) align_size_up((intptr_t)ptr, alignment); +} + +// Trace if verbose to tty. +// I use these now instead of the Xtrace system because the latter is +// not available at init time, hence worthless. Until we fix this, all +// tracing here is done with -XX:+Verbose. +#define trcVerbose(fmt, ...) { \ + if (Verbose) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fputc('\n', stderr); fflush(stderr); \ + } \ +} +#define ERRBYE(s) { trcVerbose(s); return -1; } + +// Unfortunately, the interface of dladdr makes the implementator +// responsible for maintaining memory for function name/library +// name. I guess this is because most OS's keep those values as part +// of the mapped executable image ready to use. On AIX, this doesn't +// work, so I have to keep the returned strings. For now, I do this in +// a primitive string map. Should this turn out to be a performance +// problem, a better hashmap has to be used. +class fixed_strings { + struct node { + char* v; + node* next; + }; + + node* first; + + public: + + fixed_strings() : first(0) {} + ~fixed_strings() { + node* n = first; + while (n) { + node* p = n; + n = n->next; + free(p->v); + delete p; + } + } + + char* intern(const char* s) { + for (node* n = first; n; n = n->next) { + if (strcmp(n->v, s) == 0) { + return n->v; + } + } + node* p = new node; + p->v = strdup(s); + p->next = first; + first = p; + return p->v; + } +}; + +static fixed_strings dladdr_fixed_strings; + +// Given a code pointer, returns the function name and the displacement. +// Function looks for the traceback table at the end of the function. +extern "C" int getFuncName( + codeptr_t pc, // [in] program counter + char* p_name, size_t namelen, // [out] optional: function name ("" if not available) + int* p_displacement, // [out] optional: displacement (-1 if not available) + const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further + // information (NULL if not available) + char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages + ) { + struct tbtable* tb = 0; + unsigned int searchcount = 0; + + // initialize output parameters + if (p_name && namelen > 0) { + *p_name = '\0'; + } + if (p_errmsg && errmsglen > 0) { + *p_errmsg = '\0'; + } + if (p_displacement) { + *p_displacement = -1; + } + if (p_tb) { + *p_tb = NULL; + } + + // weed out obvious bogus states + if (pc < MINIMUM_VALUE_FOR_PC) { + ERRBYE("invalid program counter"); + } + + codeptr_t pc2 = pc; + + // make sure the pointer is word aligned. + pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4); + + // Find start of traceback table. + // (starts after code, is marked by word-aligned (32bit) zeros) + while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) { + pc2++; + } + if (*pc2 != 0) { + ERRBYE("could not find traceback table within 5000 bytes of program counter"); + } + // + // Set up addressability to the traceback table + // + tb = (struct tbtable*) (pc2 + 1); + + // Is this really a traceback table? No way to be sure but + // some indicators we can check. + if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) { + // Language specifiers, go from 0 (C) to 14 (Objective C). + // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm. + ERRBYE("not a traceback table"); + } + + // Existence of fields in the tbtable extension are contingent upon + // specific fields in the base table. Check for their existence so + // that we can address the function name if it exists. + pc2 = (codeptr_t) tb + + sizeof(struct tbtable_short)/sizeof(int); + if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0) + pc2++; + + if (tb->tb.has_tboff == TRUE) { + + // I want to know the displacement + const unsigned int tb_offset = *pc2; + codeptr_t start_of_procedure = + (codeptr_t)(((char*)tb) - 4 - tb_offset); // (-4 to omit leading 0000) + + // Weed out the cases where we did find the wrong traceback table. + if (pc < start_of_procedure) { + ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter"); + } + + // return the displacement + if (p_displacement) { + (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure); + } + + pc2++; + } else { + // return -1 for displacement + if (p_displacement) { + (*p_displacement) = -1; + } + } + + if (tb->tb.int_hndl == TRUE) + pc2++; + + if (tb->tb.has_ctl == TRUE) + pc2 += (*pc2) + 1; // don't care + + // + // return function name if it exists. + // + if (p_name && namelen > 0) { + if (tb->tb.name_present) { + char buf[256]; + const short l = MIN2(*((short*)pc2), sizeof(buf) - 1); + memcpy(buf, (char*)pc2 + sizeof(short), l); + buf[l] = '\0'; + + p_name[0] = '\0'; + + // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h). + char* rest; + Name* const name = Demangle(buf, rest); + if (name) { + const char* const demangled_name = name->Text(); + if (demangled_name) { + strncpy(p_name, demangled_name, namelen-1); + p_name[namelen-1] = '\0'; + } + delete name; + } + + // Fallback: if demangling did not work, just provide the unmangled name. + if (p_name[0] == '\0') { + strncpy(p_name, buf, namelen-1); + p_name[namelen-1] = '\0'; + } + + } else { + strncpy(p_name, "", namelen-1); + p_name[namelen-1] = '\0'; + } + } + // Return traceback table, if user wants it. + if (p_tb) { + (*p_tb) = tb; + } + + return 0; +} + +// Special implementation of dladdr for Aix based on LoadedLibraries +// Note: dladdr returns non-zero for ok, 0 for error! +// Note: dladdr is not posix, but a non-standard GNU extension. So this tries to +// fulfill the contract of dladdr on Linux (see http://linux.die.net/man/3/dladdr) +// Note: addr may be both an AIX function descriptor or a real code pointer +// to the entry of a function. +extern "C" +int dladdr(void* addr, Dl_info* info) { + + if (!addr) { + return 0; + } + + assert(info, ""); + + int rc = 0; + + const char* const ZEROSTRING = ""; + + // Always return a string, even if a "" one. Linux dladdr manpage + // does not say anything about returning NULL + info->dli_fname = ZEROSTRING; + info->dli_sname = ZEROSTRING; + info->dli_saddr = NULL; + + address p = (address) addr; + const LoadedLibraryModule* lib = NULL; + + enum { noclue, code, data } type = noclue; + + trcVerbose("dladdr(%p)...", p); + + // Note: input address may be a function. I accept both a pointer to + // the entry of a function and a pointer to the function decriptor. + // (see ppc64 ABI) + lib = LoadedLibraries::find_for_text_address(p); + if (lib) { + type = code; + } + + if (!lib) { + // Not a pointer into any text segment. Is it a function descriptor? + const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p; + p = pfd->entry(); + if (p) { + lib = LoadedLibraries::find_for_text_address(p); + if (lib) { + type = code; + } + } + } + + if (!lib) { + // Neither direct code pointer nor function descriptor. A data ptr? + p = (address)addr; + lib = LoadedLibraries::find_for_data_address(p); + if (lib) { + type = data; + } + } + + // If we did find the shared library this address belongs to (either + // code or data segment) resolve library path and, if possible, the + // symbol name. + if (lib) { + const char* const interned_libpath = + dladdr_fixed_strings.intern(lib->get_fullpath()); + if (interned_libpath) { + info->dli_fname = interned_libpath; + } + + if (type == code) { + + // For code symbols resolve function name and displacement. Use + // displacement to calc start of function. + char funcname[256] = ""; + int displacement = 0; + + if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement, + NULL, NULL, 0) == 0) { + if (funcname[0] != '\0') { + const char* const interned = dladdr_fixed_strings.intern(funcname); + info->dli_sname = interned; + trcVerbose("... function name: %s ...", interned); + } + + // From the displacement calculate the start of the function. + if (displacement != -1) { + info->dli_saddr = p - displacement; + } else { + info->dli_saddr = p; + } + } else { + + // No traceback table found. Just assume the pointer is it. + info->dli_saddr = p; + + } + + } else if (type == data) { + + // For data symbols. + info->dli_saddr = p; + + } else { + ShouldNotReachHere(); + } + + rc = 1; // success: return 1 [sic] + + } + + // sanity checks. + if (rc) { + assert(info->dli_fname, ""); + assert(info->dli_sname, ""); + assert(info->dli_saddr, ""); + } + + return rc; // error: return 0 [sic] + +} diff --git a/hotspot/src/os/aix/vm/porting_aix.hpp b/hotspot/src/os/aix/vm/porting_aix.hpp new file mode 100644 index 00000000000..53f9939937f --- /dev/null +++ b/hotspot/src/os/aix/vm/porting_aix.hpp @@ -0,0 +1,81 @@ +/* + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 + +// Header file to contain porting-relevant code which does not have a +// home anywhere else and which can not go into os_.h because +// that header is included inside the os class definition, hence all +// its content is part of the os class. + +// Aix' own version of dladdr(). +// This function tries to mimick dladdr(3) on Linux +// (see http://linux.die.net/man/3/dladdr) +// dladdr(3) is not POSIX but a GNU extension, and is not available on AIX. +// +// Differences between AIX dladdr and Linux dladdr: +// +// 1) Dl_info.dli_fbase: can never work, is disabled. +// A loaded image on AIX is divided in multiple segments, at least two +// (text and data) but potentially also far more. This is because the loader may +// load each member into an own segment, as for instance happens with the libC.a +// 2) Dl_info.dli_sname: This only works for code symbols (functions); for data, a +// zero-length string is returned (""). +// 3) Dl_info.dli_saddr: For code, this will return the entry point of the function, +// not the function descriptor. + +typedef struct { + const char *dli_fname; // file path of loaded library + // void *dli_fbase; + const char *dli_sname; // symbol name; "" if not known + void *dli_saddr; // address of *entry* of function; not function descriptor; +} Dl_info; + +// Note: we export this to use it inside J2se too +#ifdef __cplusplus +extern "C" +#endif +int dladdr(void *addr, Dl_info *info); + + +// The semantics in this file are thus that codeptr_t is a *real code ptr*. +// This means that any function taking codeptr_t as arguments will assume +// a real codeptr and won't handle function descriptors (eg getFuncName), +// whereas functions taking address as args will deal with function +// descriptors (eg os::dll_address_to_library_name). +typedef unsigned int* codeptr_t; + +// helper function - given a program counter, tries to locate the traceback table and +// returns info from it (like, most importantly, function name, displacement of the +// pc inside the function, and the traceback table itself. +#ifdef __cplusplus +extern "C" +#endif +int getFuncName( + codeptr_t pc, // [in] program counter + char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name + int* p_displacement, // [out] optional: displacement + const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information + char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages + ); diff --git a/hotspot/src/os/aix/vm/threadCritical_aix.cpp b/hotspot/src/os/aix/vm/threadCritical_aix.cpp new file mode 100644 index 00000000000..a7cc96fce35 --- /dev/null +++ b/hotspot/src/os/aix/vm/threadCritical_aix.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/threadCritical.hpp" +#include "thread_aix.inline.hpp" + +// put OS-includes here +# include + +// +// See threadCritical.hpp for details of this class. +// + +static pthread_t tc_owner = 0; +static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int tc_count = 0; + +void ThreadCritical::initialize() { +} + +void ThreadCritical::release() { +} + +ThreadCritical::ThreadCritical() { + pthread_t self = pthread_self(); + if (self != tc_owner) { + int ret = pthread_mutex_lock(&tc_mutex); + guarantee(ret == 0, "fatal error with pthread_mutex_lock()"); + assert(tc_count == 0, "Lock acquired with illegal reentry count."); + tc_owner = self; + } + tc_count++; +} + +ThreadCritical::~ThreadCritical() { + assert(tc_owner == pthread_self(), "must have correct owner"); + assert(tc_count > 0, "must have correct count"); + + tc_count--; + if (tc_count == 0) { + tc_owner = 0; + int ret = pthread_mutex_unlock(&tc_mutex); + guarantee(ret == 0, "fatal error with pthread_mutex_unlock()"); + } +} diff --git a/hotspot/src/os/aix/vm/thread_aix.inline.hpp b/hotspot/src/os/aix/vm/thread_aix.inline.hpp new file mode 100644 index 00000000000..27120241f61 --- /dev/null +++ b/hotspot/src/os/aix/vm/thread_aix.inline.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_AIX_VM_THREAD_AIX_INLINE_HPP +#define OS_AIX_VM_THREAD_AIX_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/prefetch.hpp" +#include "runtime/thread.hpp" +#include "runtime/threadLocalStorage.hpp" + +#include "atomic_aix_ppc.inline.hpp" +#include "orderAccess_aix_ppc.inline.hpp" +#include "prefetch_aix_ppc.inline.hpp" + +// Contains inlined functions for class Thread and ThreadLocalStorage + +inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do + +#endif // OS_AIX_VM_THREAD_AIX_INLINE_HPP diff --git a/hotspot/src/os/aix/vm/vmError_aix.cpp b/hotspot/src/os/aix/vm/vmError_aix.cpp new file mode 100644 index 00000000000..d99436ebc1c --- /dev/null +++ b/hotspot/src/os/aix/vm/vmError_aix.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/arguments.hpp" +#include "runtime/os.hpp" +#include "runtime/thread.hpp" +#include "utilities/vmError.hpp" + +#include +#include +#include +#include + +void VMError::show_message_box(char *buf, int buflen) { + bool yes; + do { + error_string(buf, buflen); + int len = (int)strlen(buf); + char *p = &buf[len]; + + jio_snprintf(p, buflen - len, + "\n\n" + "Do you want to debug the problem?\n\n" + "To debug, run 'dbx -a %d'; then switch to thread tid " INTX_FORMAT ", k-tid " INTX_FORMAT "\n" + "Enter 'yes' to launch dbx automatically (PATH must include dbx)\n" + "Otherwise, press RETURN to abort...", + os::current_process_id(), + os::current_thread_id(), thread_self()); + + yes = os::message_box("Unexpected Error", buf); + + if (yes) { + // yes, user asked VM to launch debugger + jio_snprintf(buf, buflen, "dbx -a %d", os::current_process_id()); + + os::fork_and_exec(buf); + yes = false; + } + } while (yes); +} + +// Handle all synchronous signals which may happen during signal handling, +// not just SIGSEGV and SIGBUS. +static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed +static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int); + +// Space for our "saved" signal flags and handlers +static int resettedSigflags[NUM_SIGNALS]; +static address resettedSighandler[NUM_SIGNALS]; + +static void save_signal(int idx, int sig) { + struct sigaction sa; + sigaction(sig, NULL, &sa); + resettedSigflags[idx] = sa.sa_flags; + resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) + : CAST_FROM_FN_PTR(address, sa.sa_handler); +} + +int VMError::get_resetted_sigflags(int sig) { + // Handle all program errors. + for (int i = 0; i < NUM_SIGNALS; i++) { + if (SIGNALS[i] == sig) { + return resettedSigflags[i]; + } + } + return -1; +} + +address VMError::get_resetted_sighandler(int sig) { + // Handle all program errors. + for (int i = 0; i < NUM_SIGNALS; i++) { + if (SIGNALS[i] == sig) { + return resettedSighandler[i]; + } + } + return NULL; +} + +static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { + // Unmask current signal. + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + + Unimplemented(); +} + +void VMError::reset_signal_handlers() { + sigset_t newset; + sigemptyset(&newset); + + for (int i = 0; i < NUM_SIGNALS; i++) { + save_signal(i, SIGNALS[i]); + os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler)); + sigaddset(&newset, SIGNALS[i]); + } + + sigthreadmask(SIG_UNBLOCK, &newset, NULL); +} diff --git a/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp new file mode 100644 index 00000000000..c7f8a26163f --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp @@ -0,0 +1,401 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP +#define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP + +#include "orderAccess_aix_ppc.inline.hpp" +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#include "vm_version_ppc.hpp" + +#ifndef _LP64 +#error "Atomic currently only impleneted for PPC64" +#endif + +// Implementation of class atomic + +inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } + +inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } + +inline jlong Atomic::load(volatile jlong* src) { return *src; } + +/* + machine barrier instructions: + + - ppc_sync two-way memory barrier, aka fence + - ppc_lwsync orders Store|Store, + Load|Store, + Load|Load, + but not Store|Load + - ppc_eieio orders memory accesses for device memory (only) + - ppc_isync invalidates speculatively executed instructions + From the POWER ISA 2.06 documentation: + "[...] an isync instruction prevents the execution of + instructions following the isync until instructions + preceding the isync have completed, [...]" + From IBM's AIX assembler reference: + "The isync [...] instructions causes the processor to + refetch any instructions that might have been fetched + prior to the isync instruction. The instruction isync + causes the processor to wait for all previous instructions + to complete. Then any instructions already fetched are + discarded and instruction processing continues in the + environment established by the previous instructions." + + semantic barrier instructions: + (as defined in orderAccess.hpp) + + - ppc_release orders Store|Store, (maps to ppc_lwsync) + Load|Store + - ppc_acquire orders Load|Store, (maps to ppc_lwsync) + Load|Load + - ppc_fence orders Store|Store, (maps to ppc_sync) + Load|Store, + Load|Load, + Store|Load +*/ + +#define strasm_ppc_sync "\n sync \n" +#define strasm_ppc_lwsync "\n lwsync \n" +#define strasm_ppc_isync "\n isync \n" +#define strasm_ppc_release strasm_ppc_lwsync +#define strasm_ppc_acquire strasm_ppc_lwsync +#define strasm_ppc_fence strasm_ppc_sync +#define strasm_ppc_nobarrier "" +#define strasm_ppc_nobarrier_clobber_memory "" + +inline jint Atomic::add (jint add_value, volatile jint* dest) { + + unsigned int result; + + __asm__ __volatile__ ( + strasm_ppc_lwsync + "1: lwarx %0, 0, %2 \n" + " add %0, %0, %1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_isync + : /*%0*/"=&r" (result) + : /*%1*/"r" (add_value), /*%2*/"r" (dest) + : "cc", "memory" ); + + return (jint) result; +} + + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + + long result; + + __asm__ __volatile__ ( + strasm_ppc_lwsync + "1: ldarx %0, 0, %2 \n" + " add %0, %0, %1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_isync + : /*%0*/"=&r" (result) + : /*%1*/"r" (add_value), /*%2*/"r" (dest) + : "cc", "memory" ); + + return (intptr_t) result; +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)add_ptr(add_value, (volatile intptr_t*)dest); +} + + +inline void Atomic::inc (volatile jint* dest) { + + unsigned int temp; + + __asm__ __volatile__ ( + strasm_ppc_nobarrier + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, 1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_ppc_nobarrier_clobber_memory); + +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + + long temp; + + __asm__ __volatile__ ( + strasm_ppc_nobarrier + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, 1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_ppc_nobarrier_clobber_memory); + +} + +inline void Atomic::inc_ptr(volatile void* dest) { + inc_ptr((volatile intptr_t*)dest); +} + + +inline void Atomic::dec (volatile jint* dest) { + + unsigned int temp; + + __asm__ __volatile__ ( + strasm_ppc_nobarrier + "1: lwarx %0, 0, %2 \n" + " addic %0, %0, -1 \n" + " stwcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_ppc_nobarrier_clobber_memory); + +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + + long temp; + + __asm__ __volatile__ ( + strasm_ppc_nobarrier + "1: ldarx %0, 0, %2 \n" + " addic %0, %0, -1 \n" + " stdcx. %0, 0, %2 \n" + " bne- 1b \n" + strasm_ppc_nobarrier + : /*%0*/"=&r" (temp), "=m" (*dest) + : /*%2*/"r" (dest), "m" (*dest) + : "cc" strasm_ppc_nobarrier_clobber_memory); + +} + +inline void Atomic::dec_ptr(volatile void* dest) { + dec_ptr((volatile intptr_t*)dest); +} + +inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) { + + // Note that xchg_ptr doesn't necessarily do an acquire + // (see synchronizer.cpp). + + unsigned int old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* lwsync */ + strasm_ppc_lwsync + /* atomic loop */ + "1: \n" + " lwarx %[old_value], %[dest], %[zero] \n" + " stwcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* isync */ + strasm_ppc_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jint) old_value; +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + + // Note that xchg_ptr doesn't necessarily do an acquire + // (see synchronizer.cpp). + + long old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* lwsync */ + strasm_ppc_lwsync + /* atomic loop */ + "1: \n" + " ldarx %[old_value], %[dest], %[zero] \n" + " stdcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* isync */ + strasm_ppc_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (intptr_t) old_value; +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); +} + +inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) { + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' + // (see atomic.hpp). + + unsigned int old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* fence */ + strasm_ppc_sync + /* simple guard */ + " lwz %[old_value], 0(%[dest]) \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " lwarx %[old_value], %[dest], %[zero] \n" + " cmpw %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stwcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* acquire */ + strasm_ppc_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jint) old_value; +} + +inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) { + + // Note that cmpxchg guarantees a two-way memory barrier across + // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire' + // (see atomic.hpp). + + long old_value; + const uint64_t zero = 0; + + __asm__ __volatile__ ( + /* fence */ + strasm_ppc_sync + /* simple guard */ + " ld %[old_value], 0(%[dest]) \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + /* atomic loop */ + "1: \n" + " ldarx %[old_value], %[dest], %[zero] \n" + " cmpd %[compare_value], %[old_value] \n" + " bne- 2f \n" + " stdcx. %[exchange_value], %[dest], %[zero] \n" + " bne- 1b \n" + /* acquire */ + strasm_ppc_sync + /* exit */ + "2: \n" + /* out */ + : [old_value] "=&r" (old_value), + "=m" (*dest) + /* in */ + : [dest] "b" (dest), + [zero] "r" (zero), + [compare_value] "r" (compare_value), + [exchange_value] "r" (exchange_value), + "m" (*dest) + /* clobber */ + : "cc", + "memory" + ); + + return (jlong) old_value; +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +#undef strasm_ppc_sync +#undef strasm_ppc_lwsync +#undef strasm_ppc_isync +#undef strasm_ppc_release +#undef strasm_ppc_acquire +#undef strasm_ppc_fence +#undef strasm_ppc_nobarrier +#undef strasm_ppc_nobarrier_clobber_memory + +#endif // OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp new file mode 100644 index 00000000000..e3203e1f529 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/globals_aix_ppc.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP +#define OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP + +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + +define_pd_global(bool, DontYieldALot, false); +define_pd_global(intx, ThreadStackSize, 2048); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 2048); + +// if we set CompilerThreadStackSize to a value different than 0, it will +// be used in os::create_thread(). Otherwise, due the strange logic in os::create_thread(), +// the stack size for compiler threads will default to VMThreadStackSize, although it +// is defined to 4M in os::Aix::default_stack_size()! +define_pd_global(intx, CompilerThreadStackSize, 4096); + +// Allow extra space in DEBUG builds for asserts. +define_pd_global(uintx,JVMInvokeMethodSlack, 8192); + +define_pd_global(intx, StackYellowPages, 6); +define_pd_global(intx, StackRedPages, 1); +define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+2)); + +// Only used on 64 bit platforms +define_pd_global(uintx,HeapBaseMinAddress, 2*G); +// Only used on 64 bit Windows platforms +define_pd_global(bool, UseVectoredExceptions, false); + +#endif // OS_CPU_AIX_OJDKPPC_VM_GLOBALS_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp new file mode 100644 index 00000000000..2eb4922aea5 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP +#define OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP + +#include "runtime/orderAccess.hpp" +#include "vm_version_ppc.hpp" + +// Implementation of class OrderAccess. + +// +// Machine barrier instructions: +// +// - ppc_sync Two-way memory barrier, aka fence. +// - ppc_lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - ppc_eieio orders Store|Store +// - ppc_isync Invalidates speculatively executed instructions, +// but isync may complete before storage accesses +// associated with instructions preceding isync have +// been performed. +// +// Semantic barrier instructions: +// (as defined in orderAccess.hpp) +// +// - ppc_release orders Store|Store, (maps to ppc_lwsync) +// Load|Store +// - ppc_acquire orders Load|Store, (maps to ppc_lwsync) +// Load|Load +// - ppc_fence orders Store|Store, (maps to ppc_sync) +// Load|Store, +// Load|Load, +// Store|Load +// + +#define inlasm_ppc_sync() __asm__ __volatile__ ("sync" : : : "memory"); +#define inlasm_ppc_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); +#define inlasm_ppc_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); +#define inlasm_ppc_isync() __asm__ __volatile__ ("isync" : : : "memory"); +#define inlasm_ppc_release() inlasm_ppc_lwsync(); +#define inlasm_ppc_acquire() inlasm_ppc_lwsync(); +// Use twi-isync for load_acquire (faster than lwsync). +// ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"): +// #define inlasm_ppc_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); +#define inlasm_ppc_acquire_reg(X) inlasm_ppc_lwsync(); +#define inlasm_ppc_fence() inlasm_ppc_sync(); + +inline void OrderAccess::loadload() { inlasm_ppc_lwsync(); } +inline void OrderAccess::storestore() { inlasm_ppc_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_ppc_lwsync(); } +inline void OrderAccess::storeload() { inlasm_ppc_fence(); } + +inline void OrderAccess::acquire() { inlasm_ppc_acquire(); } +inline void OrderAccess::release() { inlasm_ppc_release(); } +inline void OrderAccess::fence() { inlasm_ppc_fence(); } + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_ppc_acquire(); return t; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_ppc_acquire(); return t; } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_ppc_fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_ppc_fence(); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; inlasm_ppc_fence(); } + +#undef inlasm_ppc_sync +#undef inlasm_ppc_lwsync +#undef inlasm_ppc_eieio +#undef inlasm_ppc_isync +#undef inlasm_ppc_release +#undef inlasm_ppc_acquire +#undef inlasm_ppc_fence + +#endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp new file mode 100644 index 00000000000..fe3769f3068 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -0,0 +1,560 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// no precompiled headers +#include "assembler_ppc.inline.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_aix.h" +#include "memory/allocation.inline.hpp" +#include "mutex_aix.inline.hpp" +#include "nativeInst_ppc.hpp" +#include "os_share_aix.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/osThread.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/timer.hpp" +#include "thread_aix.inline.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +// put OS-includes here +# include + +address os::current_stack_pointer() { + address csp; + +#if !defined(USE_XLC_BUILTINS) + // inline assembly for `ppc_mr regno(csp), PPC_SP': + __asm__ __volatile__ ("mr %0, 1":"=r"(csp):); +#else + csp = (address) __builtin_frame_address(0); +#endif + + return csp; +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + // even in its subfields (as defined by the CPU immediate fields, + // if the CPU splits constants across multiple instructions). + + return (char*) -1; +} + +// OS specific thread initialization +// +// Calculate and store the limits of the memory stack. +void os::initialize_thread(Thread *thread) { } + +// Frame information (pc, sp, fp) retrieved via ucontext +// always looks like a C-frame according to the frame +// conventions in frame_ppc64.hpp. +address os::Aix::ucontext_get_pc(ucontext_t * uc) { + return (address)uc->uc_mcontext.jmp_context.iar; +} + +intptr_t* os::Aix::ucontext_get_sp(ucontext_t * uc) { + // gpr1 holds the stack pointer on aix + return (intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/]; +} + +intptr_t* os::Aix::ucontext_get_fp(ucontext_t * uc) { + return NULL; +} + +void os::Aix::ucontext_set_pc(ucontext_t* uc, address new_pc) { + uc->uc_mcontext.jmp_context.iar = (uint64_t) new_pc; +} + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { + + ExtendedPC epc; + ucontext_t* uc = (ucontext_t*)ucVoid; + + if (uc != NULL) { + epc = ExtendedPC(os::Aix::ucontext_get_pc(uc)); + if (ret_sp) *ret_sp = os::Aix::ucontext_get_sp(uc); + if (ret_fp) *ret_fp = os::Aix::ucontext_get_fp(uc); + } else { + // construct empty ExtendedPC for return value checking + epc = ExtendedPC(NULL); + if (ret_sp) *ret_sp = (intptr_t *)NULL; + if (ret_fp) *ret_fp = (intptr_t *)NULL; + } + + return epc; +} + +frame os::fetch_frame_from_context(void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + // Avoid crash during crash if pc broken. + if (epc.pc()) { + frame fr(sp, epc.pc()); + return fr; + } + frame fr(sp); + return fr; +} + +frame os::get_sender_for_C_frame(frame* fr) { + if (*fr->sp() == NULL) { + // fr is the last C frame + return frame(NULL, NULL); + } + return frame(fr->sender_sp(), fr->sender_pc()); +} + + +frame os::current_frame() { + intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer()); + // hack. + frame topframe(csp, (address)0x8); + // return sender of current topframe which hopefully has pc != NULL. + return os::get_sender_for_C_frame(&topframe); +} + +// Utility functions + +extern "C" JNIEXPORT int +JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) { + + ucontext_t* uc = (ucontext_t*) ucVoid; + + Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady + + SignalHandlerMark shm(t); + + // Note: it's not uncommon that JNI code uses signal/sigset to install + // then restore certain signal handler (e.g. to temporarily block SIGPIPE, + // or have a SIGILL handler when detecting CPU type). When that happens, + // JVM_handle_aix_signal() might be invoked with junk info/ucVoid. To + // avoid unnecessary crash when libjsig is not preloaded, try handle signals + // that do not require siginfo/ucontext first. + + if (sig == SIGPIPE) { + if (os::Aix::chained_handler(sig, info, ucVoid)) { + return 1; + } else { + if (PrintMiscellaneous && (WizardMode || Verbose)) { + warning("Ignoring SIGPIPE - see bug 4229104"); + } + return 1; + } + } + + JavaThread* thread = NULL; + VMThread* vmthread = NULL; + if (os::Aix::signal_handlers_are_installed) { + if (t != NULL) { + if(t->is_Java_thread()) { + thread = (JavaThread*)t; + } + else if(t->is_VM_thread()) { + vmthread = (VMThread *)t; + } + } + } + + // Decide if this trap can be handled by a stub. + address stub = NULL; + + // retrieve program counter + address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL; + + // retrieve crash address + address const addr = info ? (const address) info->si_addr : NULL; + + // SafeFetch 32 handling: + // - make it work if _thread is null + // - make it use the standard os::...::ucontext_get/set_pc APIs + if (uc) { + address const pc = os::Aix::ucontext_get_pc(uc); + if (pc && StubRoutines::is_safefetch_fault(pc)) { + os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); + return true; + } + } + + // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap + // space falls below 30%. This is only a chance for the process to gracefully abort. + // We can't hope to proceed after SIGDANGER since SIGKILL tailgates. + if (sig == SIGDANGER) { + goto report_and_die; + } + + if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) { + goto run_chained_handler; + } + + // If we are a java thread... + if (thread != NULL) { + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV && (addr < thread->stack_base() && + addr >= thread->stack_base() - thread->stack_size())) { + // stack overflow + // + // If we are in a yellow zone and we are inside java, we disable the yellow zone and + // throw a stack overflow exception. + // If we are in native code or VM C code, we report-and-die. The original coding tried + // to continue with yellow zone disabled, but that doesn't buy us much and prevents + // hs_err_pid files. + if (thread->in_stack_yellow_zone(addr)) { + thread->disable_stack_yellow_zone(); + if (thread->thread_state() == _thread_in_Java) { + // Throw a stack overflow exception. + // Guard pages will be reenabled while unwinding the stack. + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); + goto run_stub; + } else { + // Thread was in the vm or native code. Return and try to finish. + return 1; + } + } else if (thread->in_stack_red_zone(addr)) { + // Fatal red zone violation. Disable the guard pages and fall through + // to handle_unexpected_exception way down below. + thread->disable_stack_red_zone(); + tty->print_raw_cr("An irrecoverable stack overflow has occurred."); + goto report_and_die; + } else { + // this means a segv happened inside our stack, but not in + // the guarded zone. I'd like to know when this happens, + tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone."); + goto report_and_die; + } + + } // end handle SIGSEGV inside stack boundaries + + if (thread->thread_state() == _thread_in_Java) { + // Java thread running in Java code + + // The following signals are used for communicating VM events: + // + // SIGILL: the compiler generates illegal opcodes + // at places where it wishes to interrupt the VM: + // Safepoints, Unreachable Code, Entry points of Zombie methods, + // This results in a SIGILL with (*pc) == inserted illegal instruction. + // + // (so, SIGILLs with a pc inside the zero page are real errors) + // + // SIGTRAP: + // The ppc trap instruction raises a SIGTRAP and is very efficient if it + // does not trap. It is used for conditional branches that are expected + // to be never taken. These are: + // - zombie methods + // - IC (inline cache) misses. + // - null checks leading to UncommonTraps. + // - range checks leading to Uncommon Traps. + // On Aix, these are especially null checks, as the ImplicitNullCheck + // optimization works only in rare cases, as the page at address 0 is only + // write protected. // + // Note: !UseSIGTRAP is used to prevent SIGTRAPS altogether, to facilitate debugging. + // + // SIGSEGV: + // used for safe point polling: + // To notify all threads that they have to reach a safe point, safe point polling is used: + // All threads poll a certain mapped memory page. Normally, this page has read access. + // If the VM wants to inform the threads about impending safe points, it puts this + // page to read only ("poisens" the page), and the threads then reach a safe point. + // used for null checks: + // If the compiler finds a store it uses it for a null check. Unfortunately this + // happens rarely. In heap based and disjoint base compressd oop modes also loads + // are used for null checks. + + // A VM-related SIGILL may only occur if we are not in the zero page. + // On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else + // in the zero page, because it is filled with 0x0. We ignore + // explicit SIGILLs in the zero page. + if (sig == SIGILL && (pc < (address) 0x200)) { + if (TraceTraps) + tty->print_raw_cr("SIGILL happened inside zero page."); + goto report_and_die; + } + + // Handle signal from NativeJump::patch_verified_entry(). + if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) || + (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) { + if (TraceTraps) + tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + stub = SharedRuntime::get_handle_wrong_method_stub(); + goto run_stub; + } + + else if (sig == SIGSEGV && os::is_poll_address(addr)) { + if (TraceTraps) + tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc); + stub = SharedRuntime::get_poll_stub(pc); + goto run_stub; + } + + // SIGTRAP-based ic miss check in compiled code + else if (sig == SIGTRAP && TrapBasedICMissChecks && + nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) { + if (TraceTraps) + tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::get_ic_miss_stub(); + goto run_stub; + } + +#ifdef COMPILER2 + // SIGTRAP-based implicit null check in compiled code. + else if (sig == SIGTRAP && TrapBasedNullChecks && + nativeInstruction_at(pc)->is_sigtrap_null_check()) { + if (TraceTraps) + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + goto run_stub; + } +#endif + + // SIGSEGV-based implicit null check in compiled code. + else if (sig == SIGSEGV && ImplicitNullChecks && + CodeCache::contains((void*) pc) && + !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) { + if (TraceTraps) + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } + +#ifdef COMPILER2 + // SIGTRAP-based implicit range check in compiled code. + else if (sig == SIGTRAP && TrapBasedRangeChecks && + nativeInstruction_at(pc)->is_sigtrap_range_check()) { + if (TraceTraps) + tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + goto run_stub; + } +#endif + + else if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) { + if (TraceTraps) { + tty->print_raw_cr("Fix SIGFPE handler, trying divide by zero handler."); + } + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); + goto run_stub; + } + + else if (sig == SIGBUS) { + // BugId 4454115: A read from a MappedByteBuffer can fault here if the + // underlying file has been truncated. Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; + if (nm != NULL && nm->has_unsafe_access()) { + // We don't really need a stub here! Just set the pending exeption and + // continue at the next instruction after the faulting read. Returning + // garbage from this read is ok. + thread->set_pending_unsafe_access_error(); + uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4; + return 1; + } + } + } + + else { // thread->thread_state() != _thread_in_Java + // Detect CPU features. This is only done at the very start of the VM. Later, the + // VM_Version::is_determine_features_test_running() flag should be false. + + if (sig == SIGILL && VM_Version::is_determine_features_test_running()) { + // SIGILL must be caused by VM_Version::determine_features(). + *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL, + // flushing of icache is not necessary. + stub = pc + 4; // continue with next instruction. + goto run_stub; + } + else if (thread->thread_state() == _thread_in_vm && + sig == SIGBUS && thread->doing_unsafe_access()) { + // We don't really need a stub here! Just set the pending exeption and + // continue at the next instruction after the faulting read. Returning + // garbage from this read is ok. + thread->set_pending_unsafe_access_error(); + uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4; + return 1; + } + } + + // Check to see if we caught the safepoint code in the + // process of write protecting the memory serialization page. + // It write enables the page immediately after protecting it + // so we can just return to retry the write. + if ((sig == SIGSEGV) && + os::is_memory_serialize_page(thread, addr)) { + // Synchronization problem in the pseudo memory barrier code (bug id 6546278) + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return true; + } + } + +run_stub: + + // One of the above code blocks ininitalized the stub, so we want to + // delegate control to that stub. + if (stub != NULL) { + // Save all thread context in case we need to restore it. + if (thread != NULL) thread->set_saved_exception_pc(pc); + uc->uc_mcontext.jmp_context.iar = (unsigned long)stub; + return 1; + } + +run_chained_handler: + + // signal-chaining + if (os::Aix::chained_handler(sig, info, ucVoid)) { + return 1; + } + if (!abort_if_unrecognized) { + // caller wants another chance, so give it to him + return 0; + } + +report_and_die: + + // Use sigthreadmask instead of sigprocmask on AIX and unmask current signal. + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + sigthreadmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(t, sig, pc, info, ucVoid); + err.report_and_die(); + + ShouldNotReachHere(); + return 0; +} + +void os::Aix::init_thread_fpu_state(void) { +#if !defined(USE_XLC_BUILTINS) + // Disable FP exceptions. + __asm__ __volatile__ ("mtfsfi 6,0"); +#else + __mtfsfi(6, 0); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// thread stack + +size_t os::Aix::min_stack_allowed = 768*K; + +// Aix is always in floating stack mode. The stack size for a new +// thread can be set via pthread_attr_setstacksize(). +bool os::Aix::supports_variable_stack_size() { return true; } + +// return default stack size for thr_type +size_t os::Aix::default_stack_size(os::ThreadType thr_type) { + // default stack size (compiler thread needs larger stack) + // Notice that the setting for compiler threads here have no impact + // because of the strange 'fallback logic' in os::create_thread(). + // Better set CompilerThreadStackSize in globals_.hpp if you want to + // specify a different stack size for compiler threads! + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K); + return s; +} + +size_t os::Aix::default_guard_size(os::ThreadType thr_type) { + return 2 * page_size(); +} + +///////////////////////////////////////////////////////////////////////////// +// helper functions for fatal error handler + +void os::print_context(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t* uc = (ucontext_t*)context; + + st->print_cr("Registers:"); + st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.iar); + st->print("lr =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.lr); + st->print("ctr=" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.ctr); + st->cr(); + for (int i = 0; i < 32; i++) { + st->print("r%-2d=" INTPTR_FORMAT " ", i, uc->uc_mcontext.jmp_context.gpr[i]); + if (i % 3 == 2) st->cr(); + } + st->cr(); + st->cr(); + + intptr_t *sp = (intptr_t *)os::Aix::ucontext_get_sp(uc); + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); + print_hex_dump(st, (address)sp, (address)(sp + 128), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::Aix::ucontext_get_pc(uc); + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); + print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4); + st->cr(); + + // Try to decode the instructions. + st->print_cr("Decoded instructions: (pc=" PTR_FORMAT ")", pc); + st->print(""); + // TODO: PPC port Disassembler::decode(pc, 16, 16, st); + st->cr(); +} + +void os::print_register_info(outputStream *st, void *context) { + if (context == NULL) return; + st->print("Not ported - print_register_info\n"); +} + +extern "C" { + int SpinPause() { + return 0; + } +} + +#ifndef PRODUCT +void os::verify_stack_alignment() { + assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); +} +#endif diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp new file mode 100644 index 00000000000..4f307279399 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP +#define OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP + + static void setup_fpu() {} + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + +#endif // OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp new file mode 100644 index 00000000000..3d855f7d0d3 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP +#define OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP + +#include "runtime/prefetch.hpp" + + +inline void Prefetch::read(void *loc, intx interval) { +#if !defined(USE_XLC_BUILTINS) + __asm__ __volatile__ ( + " dcbt 0, %0 \n" + : + : /*%0*/"r" ( ((address)loc) +((long)interval) ) + //: + ); +#else + __dcbt(((address)loc) +((long)interval)); +#endif +} + +inline void Prefetch::write(void *loc, intx interval) { +#if !defined(USE_XLC_PREFETCH_WRITE_BUILTIN) + __asm__ __volatile__ ( + " dcbtst 0, %0 \n" + : + : /*%0*/"r" ( ((address)loc) +((long)interval) ) + //: + ); +#else + __dcbtst( ((address)loc) +((long)interval) ); +#endif +} + +#endif // OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp new file mode 100644 index 00000000000..fa7ebf72bc4 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/threadLocalStorage.hpp" +#include "thread_aix.inline.hpp" + +void ThreadLocalStorage::generate_code_for_get_thread() { + // nothing we can do here for user-level thread +} + +void ThreadLocalStorage::pd_init() { + // Nothing to do +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} diff --git a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp new file mode 100644 index 00000000000..1aacc8f456a --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP +#define OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP + + // Processor dependent parts of ThreadLocalStorage + +public: + static Thread* thread() { + return (Thread *) os::thread_local_storage_at(thread_index()); + } + +#endif // OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp new file mode 100644 index 00000000000..6e8572490ca --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/frame.inline.hpp" +#include "thread_aix.inline.hpp" + +// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC. +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { + Unimplemented(); + return false; +} + +void JavaThread::cache_global_variables() { } diff --git a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp new file mode 100644 index 00000000000..c74b43e16b7 --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP +#define OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP + + private: + void pd_initialize() { + _anchor.clear(); + _last_interpreter_fp = NULL; + } + + // The `last' frame is the youngest Java frame on the thread's stack. + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + + intptr_t* sp = last_Java_sp(); + address pc = _anchor.last_Java_pc(); + + // Last_Java_pc ist not set, if we come here from compiled code. + if (pc == NULL) + pc = (address) *(sp + 2); + + return frame(sp, pc); + } + + public: + void set_base_of_stack_pointer(intptr_t* base_sp) {} + intptr_t* base_of_stack_pointer() { return NULL; } + void record_base_of_stack_pointer() {} + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + // -Xprof support + // + // In order to find the last Java fp from an async profile + // tick, we store the current interpreter fp in the thread. + // This value is only valid while we are in the C++ interpreter + // and profiling. + protected: + intptr_t *_last_interpreter_fp; + + public: + static ByteSize last_interpreter_fp_offset() { + return byte_offset_of(JavaThread, _last_interpreter_fp); + } + + intptr_t* last_interpreter_fp() { return _last_interpreter_fp; } + +#endif // OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp new file mode 100644 index 00000000000..a892c92126b --- /dev/null +++ b/hotspot/src/os_cpu/aix_ppc/vm/vmStructs_aix_ppc.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP +#define OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + nonstatic_field(OSThread, _thread_id, pid_t) \ + nonstatic_field(OSThread, _pthread_id, pthread_t) + + +#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ + \ + /**********************/ \ + /* Posix Thread IDs */ \ + /**********************/ \ + \ + declare_integer_type(pid_t) \ + declare_unsigned_integer_type(pthread_t) + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // OS_CPU_AIX_OJDKPPC_VM_VMSTRUCTS_AIX_PPC_HPP diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp new file mode 100644 index 00000000000..8a340062129 --- /dev/null +++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP +#define SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP + +#include "prims/jni.h" + +// This file holds compiler-dependent includes, +// globally used constants & types, class (forward) +// declarations and a few frequently used utility functions. + +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef FP_PZERO +// Linux doesn't have positive/negative zero +#define FP_PZERO FP_ZERO +#endif +#if (!defined fpclass) +#define fpclass fpclassify +#endif + +#include +#include +#include +#include + +#include +#include + +#include + +// Use XLC compiler builtins instead of inline assembler +#define USE_XLC_BUILTINS +#ifdef USE_XLC_BUILTINS +#include + #if __IBMCPP__ < 1000 + // the funtion prototype for __dcbtst(void *) is missing in XLC V8.0 + // I could compile a little test, where I provided the prototype. + // The generated code was correct there. This is the prototype: + // extern "builtin" void __dcbtst (void *); + // For now we don't make use of it when compiling with XLC V8.0 + #else + // __IBMCPP__ >= 1000 + // XLC V10 provides the prototype for __dcbtst (void *); + #define USE_XLC_PREFETCH_WRITE_BUILTIN + #endif +#endif // USE_XLC_BUILTINS + +// NULL vs NULL_WORD: +// On Linux NULL is defined as a special type '__null'. Assigning __null to +// integer variable will cause gcc warning. Use NULL_WORD in places where a +// pointer is stored as integer value. On some platforms, sizeof(intptr_t) > +// sizeof(void*), so here we want something which is integer type, but has the +// same size as a pointer. +#ifdef __GNUC__ + #error XLC and __GNUC__? +#else + #define NULL_WORD NULL +#endif + +// AIX also needs a 64 bit NULL to work as a null address pointer. +// Most system includes on AIX would define it as an int 0 if not already defined with one +// exception: /usr/include/dirent.h will unconditionally redefine NULL to int 0 again. +// In this case you need to copy the following defines to a position after #include +// (see jmv_aix.h). +#ifdef AIX + #ifdef _LP64 + #undef NULL + #define NULL 0L + #else + #ifndef NULL + #define NULL 0 + #endif + #endif +#endif // AIX + +// Compiler-specific primitive types +// All defs of int (uint16_6 etc) are defined in AIX' /usr/include/stdint.h + +// Additional Java basic types + +typedef uint8_t jubyte; +typedef uint16_t jushort; +typedef uint32_t juint; +typedef uint64_t julong; + +//---------------------------------------------------------------------------------------------------- +// Special (possibly not-portable) casts +// Cast floats into same-size integers and vice-versa w/o changing bit-pattern +// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar + +inline jint jint_cast (jfloat x) { return *(jint* )&x; } +inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } + +inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } +inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } + +//---------------------------------------------------------------------------------------------------- +// Constant for jlong (specifying an long long canstant is C++ compiler specific) + +// Build a 64bit integer constant +#define CONST64(x) (x ## LL) +#define UCONST64(x) (x ## ULL) + +const jlong min_jlong = CONST64(0x8000000000000000); +const jlong max_jlong = CONST64(0x7fffffffffffffff); + +//---------------------------------------------------------------------------------------------------- +// Debugging + +#define DEBUG_EXCEPTION ::abort(); + +extern "C" void breakpoint(); +#define BREAKPOINT ::breakpoint() + +// checking for nanness +#ifdef AIX +inline int g_isnan(float f) { return isnan(f); } +inline int g_isnan(double f) { return isnan(f); } +#else +#error "missing platform-specific definition here" +#endif + +// Checking for finiteness + +inline int g_isfinite(jfloat f) { return finite(f); } +inline int g_isfinite(jdouble f) { return finite(f); } + + +// Wide characters + +inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); } + + +// Portability macros +#define PRAGMA_INTERFACE #pragma interface +#define PRAGMA_IMPLEMENTATION #pragma implementation +#define VALUE_OBJ_CLASS_SPEC + +// Formatting. +#ifdef _LP64 +#define FORMAT64_MODIFIER "l" +#else // !_LP64 +#define FORMAT64_MODIFIER "ll" +#endif // _LP64 + +// Cannot use xlc's offsetof as implementation of hotspot's +// offset_of(), because xlc warns about applying offsetof() to non-POD +// object and xlc cannot compile the expression offsetof(DataLayout, +// _cells[index]) in DataLayout::cell_offset() . Therefore we define +// offset_of as it is defined for gcc. +#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16) + +// Some constant sizes used throughout the AIX port +#define SIZE_1K ((uint64_t) 0x400ULL) +#define SIZE_4K ((uint64_t) 0x1000ULL) +#define SIZE_64K ((uint64_t) 0x10000ULL) +#define SIZE_1M ((uint64_t) 0x100000ULL) +#define SIZE_4M ((uint64_t) 0x400000ULL) +#define SIZE_8M ((uint64_t) 0x800000ULL) +#define SIZE_16M ((uint64_t) 0x1000000ULL) +#define SIZE_256M ((uint64_t) 0x10000000ULL) +#define SIZE_1G ((uint64_t) 0x40000000ULL) +#define SIZE_2G ((uint64_t) 0x80000000ULL) +#define SIZE_4G ((uint64_t) 0x100000000ULL) +#define SIZE_16G ((uint64_t) 0x400000000ULL) +#define SIZE_32G ((uint64_t) 0x800000000ULL) +#define SIZE_64G ((uint64_t) 0x1000000000ULL) +#define SIZE_1T ((uint64_t) 0x10000000000ULL) + + +#endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_XLC_HPP From 081d2454fb0c972caf182b5f5667f684f7c1967a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 12 Sep 2013 13:51:13 -0700 Subject: [PATCH 020/265] 8024344: PPC64 (part 112): C argument in register AND stack slot On PPC, the first 13 floating point arguments to C calls are passed in floating point registers. Also, all but the first 8 arguments are passed on the stack. So there can be floating point arguments that are passed on the stack and in a register. We duplicate the regs datastructure in c_calling_convention() to represent this. Reviewed-by: kvn, cjplummer --- hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp | 6 ++++-- hotspot/src/cpu/sparc/vm/sparc.ad | 4 ++-- hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 6 ++++-- hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 6 ++++-- hotspot/src/cpu/x86/vm/x86_32.ad | 2 +- hotspot/src/cpu/x86/vm/x86_64.ad | 2 +- hotspot/src/cpu/zero/vm/globals_zero.hpp | 1 + hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp | 1 + hotspot/src/cpu/zero/vm/shark_globals_zero.hpp | 1 - hotspot/src/share/vm/c1/c1_FrameMap.cpp | 2 +- hotspot/src/share/vm/runtime/sharedRuntime.hpp | 10 +++++++++- 11 files changed, 28 insertions(+), 13 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 3149dbd76d2..bfc6ba4c286 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -1118,7 +1118,9 @@ static VMReg int_stk_helper( int i ) { int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, + VMRegPair *regs2, int total_args_passed) { + assert(regs2 == NULL, "not needed on sparc"); // Return the number of VMReg stack_slots needed for the args. // This value does not include an abi space (like register window @@ -2096,7 +2098,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // the 1st six register arguments). It's weird see int_stk_helper. // int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); if (is_critical_native) { // Critical natives may have to call out so they need a save area @@ -2843,7 +2845,7 @@ nmethod *SharedRuntime::generate_dtrace_nmethod( // the 1st six register arguments). It's weird see int_stk_helper. // int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); // Calculate the total number of stack slots we will need. diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index a72bffdadeb..73f03533c2b 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -3218,7 +3218,7 @@ frame %{ // C. c_calling_convention %{ // This is obviously always outgoing - (void) SharedRuntime::c_calling_convention(sig_bt, regs, length); + (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); %} // Location of native (C/C++) and interpreter return values. This is specified to @@ -9118,7 +9118,7 @@ instruct branch_short(label labl) %{ size(4); ins_cost(BRANCH_COST); format %{ "BA $labl\t! short branch" %} - ins_encode %{ + ins_encode %{ Label* L = $labl$$label; assert(__ use_cbcond(*L), "back to back cbcond"); __ ba_short(*L); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 0fce7952a70..071171e0c60 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -977,7 +977,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, + VMRegPair *regs2, int total_args_passed) { + assert(regs2 == NULL, "not needed on x86"); // We return the amount of VMRegImpl stack slots we need to reserve for all // the arguments NOT counting out_preserve_stack_slots. @@ -1624,7 +1626,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now figure out where the args must be stored and how much stack space // they require. int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); // Compute framesize for the wrapper. We need to handlize all oops in // registers a max of 2 on x86. @@ -2495,7 +2497,7 @@ nmethod *SharedRuntime::generate_dtrace_nmethod( // they require (neglecting out_preserve_stack_slots). int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); // Calculate the total number of stack slots we will need. diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index cbe960556dc..43e93806eef 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -889,7 +889,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, + VMRegPair *regs2, int total_args_passed) { + assert(regs2 == NULL, "not needed on x86"); // We return the amount of VMRegImpl stack slots we need to reserve for all // the arguments NOT counting out_preserve_stack_slots. @@ -1857,7 +1859,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now figure out where the args must be stored and how much stack space // they require. int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); // Compute framesize for the wrapper. We need to handlize all oops in // incoming registers @@ -2761,7 +2763,7 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm, // the 1st six register arguments). It's weird see int_stk_helper. int out_arg_slots; - out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args); // Calculate the total number of stack slots we will need. diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 316ebe2911d..ed76470e0a6 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -3755,7 +3755,7 @@ frame %{ // automatically biased by the preserve_stack_slots field above. c_calling_convention %{ // This is obviously always outgoing - (void) SharedRuntime::c_calling_convention(sig_bt, regs, length); + (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); %} // Location of C & interpreter return values diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index f550208e94d..c280d049e5d 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -2941,7 +2941,7 @@ frame c_calling_convention %{ // This is obviously always outgoing - (void) SharedRuntime::c_calling_convention(sig_bt, regs, length); + (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); %} // Location of compiled Java return values. Same as C for now. diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index 71b566fceb0..c0c6a857b8b 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -43,6 +43,7 @@ define_pd_global(bool, UncommonNullCast, true); define_pd_global(intx, CodeEntryAlignment, 32); define_pd_global(intx, OptoLoopAlignment, 16); define_pd_global(intx, InlineFrequencyCount, 100); +define_pd_global(intx, InlineSmallCode, 1000 ); define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, StackYellowPages, 2); diff --git a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp index 2c419b14822..33b29be3e97 100644 --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp @@ -135,6 +135,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, + VMRegPair *regs2, int total_args_passed) { ShouldNotCallThis(); return 0; diff --git a/hotspot/src/cpu/zero/vm/shark_globals_zero.hpp b/hotspot/src/cpu/zero/vm/shark_globals_zero.hpp index c04b225b830..edb7364c80f 100644 --- a/hotspot/src/cpu/zero/vm/shark_globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/shark_globals_zero.hpp @@ -50,7 +50,6 @@ define_pd_global(intx, Tier4BackEdgeThreshold, 100000); define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(intx, FreqInlineSize, 325 ); -define_pd_global(intx, InlineSmallCode, 1000 ); define_pd_global(uintx, NewRatio, 12 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(intx, InitialCodeCacheSize, 160*K); diff --git a/hotspot/src/share/vm/c1/c1_FrameMap.cpp b/hotspot/src/share/vm/c1/c1_FrameMap.cpp index f5eef6f0b3b..331690dcfd0 100644 --- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp +++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp @@ -133,7 +133,7 @@ CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signatur } } - intptr_t out_preserve = SharedRuntime::c_calling_convention(sig_bt, regs, sizeargs); + intptr_t out_preserve = SharedRuntime::c_calling_convention(sig_bt, regs, NULL, sizeargs); LIR_OprList* args = new LIR_OprList(signature->length()); for (i = 0; i < sizeargs;) { BasicType t = sig_bt[i]; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 5754536b919..8ca5da3b53d 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -356,7 +356,15 @@ class SharedRuntime: AllStatic { const VMRegPair* regs) NOT_DEBUG_RETURN; // Ditto except for calling C - static int c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, int total_args_passed); + // + // C argument in register AND stack slot. + // Some architectures require that an argument must be passed in a register + // AND in a stack slot. These architectures provide a second VMRegPair array + // to be filled by the c_calling_convention method. On other architectures, + // NULL is being passed as the second VMRegPair array, so arguments are either + // passed in a register OR in a stack slot. + static int c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, VMRegPair *regs2, + int total_args_passed); // Generate I2C and C2I adapters. These adapters are simple argument marshalling // blobs. Unlike adapters in the tiger and earlier releases the code in these From 28ae8cc785a8eaca6d1d47a9d4c2c7a507a05bab Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 13 Sep 2013 22:50:47 +0200 Subject: [PATCH 021/265] 8024469: PPC64 (part 202): cppInterpreter: support for OSR Call OSR migration with last java frame. Reviewed-by: kvn --- .../vm/interpreter/bytecodeInterpreter.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index b22ce9718db..0db00793e9a 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -345,7 +345,9 @@ nmethod* osr_nmethod; \ OSR_REQUEST(osr_nmethod, branch_pc); \ if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \ - intptr_t* buf = SharedRuntime::OSR_migration_begin(THREAD); \ + intptr_t* buf; \ + /* Call OSR migration with last java frame only, no checks. */ \ + CALL_VM_NAKED_LJF(buf=SharedRuntime::OSR_migration_begin(THREAD)); \ istate->set_msg(do_osr); \ istate->set_osr_buf((address)buf); \ istate->set_osr_entry(osr_nmethod->osr_entry()); \ @@ -418,13 +420,17 @@ CACHE_CP(); \ CACHE_LOCALS(); -// Call the VM don't check for pending exceptions -#define CALL_VM_NOCHECK(func) \ +// Call the VM with last java frame only. +#define CALL_VM_NAKED_LJF(func) \ DECACHE_STATE(); \ SET_LAST_JAVA_FRAME(); \ func; \ RESET_LAST_JAVA_FRAME(); \ - CACHE_STATE(); \ + CACHE_STATE(); + +// Call the VM. Don't check for pending exceptions. +#define CALL_VM_NOCHECK(func) \ + CALL_VM_NAKED_LJF(func) \ if (THREAD->pop_frame_pending() && \ !THREAD->pop_frame_in_process()) { \ goto handle_Pop_Frame; \ @@ -2702,7 +2708,7 @@ run: tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, continuing at %d for thread " INTPTR_FORMAT, - pc - (intptr_t)METHOD->code_base(), + istate->bcp() - (intptr_t)METHOD->code_base(), continuation_bci, THREAD); } // for AbortVMOnException flag @@ -2715,7 +2721,7 @@ run: tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, unwinding for thread " INTPTR_FORMAT, - pc - (intptr_t) METHOD->code_base(), + istate->bcp() - (intptr_t)METHOD->code_base(), THREAD); } // for AbortVMOnException flag From 5d63d647c109e584185ba07078c20ba8b401c4ef Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 18 Sep 2013 14:34:56 -0700 Subject: [PATCH 022/265] 8024342: PPC64 (part 111): Support for C calling conventions that require 64-bit ints Some platforms, as ppc and s390x/zArch require that 32-bit ints are passed as 64-bit values to C functions. This change adds support to adapt the signature and to issue proper casts to c2-compiled stubs. The functions are used in generate_native_wrapper(). Adapt signature used by the compiler as in PhaseIdealLoop::intrinsify_fill(). Reviewed-by: kvn --- .../src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 8 ++- hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 6 +- .../cpu/sparc/vm/globalDefinitions_sparc.hpp | 6 ++ .../src/cpu/x86/vm/globalDefinitions_x86.hpp | 6 ++ .../cpu/zero/vm/globalDefinitions_zero.hpp | 6 ++ .../src/share/vm/opto/generateOptoStub.cpp | 28 ++++++-- hotspot/src/share/vm/opto/loopTransform.cpp | 29 ++++++--- hotspot/src/share/vm/opto/runtime.cpp | 17 +++-- .../src/share/vm/runtime/sharedRuntime.cpp | 65 +++++++++++++++++++ .../src/share/vm/runtime/sharedRuntime.hpp | 12 +++- 10 files changed, 157 insertions(+), 26 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index 889d2857bb2..aa8b89f901c 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -29,6 +29,12 @@ // Size of PPC Instructions const int BytesPerInstWord = 4; -const int StackAlignmentInBytes = 16; +const int StackAlignmentInBytes = 16; + +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are properly extended to 64 bits. +// If set, SharedRuntime::c_calling_convention() must adapt +// signatures accordingly. +const bool CCallingConventionRequiresIntsAsLongs = true; #endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index 444882ffd2e..e9d21760130 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -734,11 +734,8 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, // We must cast ints to longs and use full 64 bit stack slots // here. We do the cast in GraphKit::gen_stub() and just guard // here against loosing that change. - Unimplemented(); // TODO: PPC port - /* - assert(SharedRuntime::c_calling_convention_requires_ints_as_longs(), + assert(CCallingConventionRequiresIntsAsLongs, "argument of type int should be promoted to type long"); - */ guarantee(i > 0 && sig_bt[i-1] == T_LONG, "argument of type (bt) should have been promoted to type (T_LONG,bt) for bt in " "{T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); @@ -856,7 +853,6 @@ static address gen_c2i_adapter(MacroAssembler *masm, const int adapter_size = frame::top_ijava_frame_abi_size + round_to(total_args_passed * wordSize, frame::alignment_in_bytes); - // regular (verified) c2i entry point c2i_entrypoint = __ pc(); diff --git a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp index cadaffe73c7..8bf65375c73 100644 --- a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp @@ -30,6 +30,12 @@ const int BytesPerInstWord = 4; const int StackAlignmentInBytes = (2*wordSize); +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are properly extended to 64 bits. +// If set, SharedRuntime::c_calling_convention() must adapt +// signatures accordingly. +const bool CCallingConventionRequiresIntsAsLongs = false; + #define SUPPORTS_NATIVE_CX8 #endif // CPU_SPARC_VM_GLOBALDEFINITIONS_SPARC_HPP diff --git a/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp b/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp index 0771794ff99..d0b685aefdc 100644 --- a/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp @@ -27,6 +27,12 @@ const int StackAlignmentInBytes = 16; +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are properly extended to 64 bits. +// If set, SharedRuntime::c_calling_convention() must adapt +// signatures accordingly. +const bool CCallingConventionRequiresIntsAsLongs = false; + #define SUPPORTS_NATIVE_CX8 #endif // CPU_X86_VM_GLOBALDEFINITIONS_X86_HPP diff --git a/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp b/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp index ceb010f3cc8..5777b8ff98f 100644 --- a/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp @@ -28,4 +28,10 @@ #include +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are properly extended to 64 bits. +// If set, SharedRuntime::c_calling_convention() must adapt +// signatures accordingly. +const bool CCallingConventionRequiresIntsAsLongs = false; + #endif // CPU_ZERO_VM_GLOBALDEFINITIONS_ZERO_HPP diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index a229faaee1e..832f9f95187 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -117,8 +117,16 @@ void GraphKit::gen_stub(address C_function, uint cnt = TypeFunc::Parms; // The C routines gets the base of thread-local storage passed in as an // extra argument. Not all calls need it, but its cheap to add here. - for( ; cntfield_at(cnt); + for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) { + // Convert ints to longs if required. + if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(pcnt)->isa_int()) { + fields[cnt++] = TypeLong::LONG; + fields[cnt] = Type::HALF; // must add an additional half for a long + } else { + fields[cnt] = jdomain->field_at(pcnt); + } + } + fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage // Also pass in the caller's PC, if asked for. if( return_pc ) @@ -169,12 +177,20 @@ void GraphKit::gen_stub(address C_function, // Set fixed predefined input arguments cnt = 0; - for( i=0; iinit_req( cnt++, map()->in(i) ); + for (i = 0; i < TypeFunc::Parms; i++) + call->init_req(cnt++, map()->in(i)); // A little too aggressive on the parm copy; return address is not an input call->set_req(TypeFunc::ReturnAdr, top()); - for( ; iinit_req( cnt++, map()->in(i) ); + for (; i < parm_cnt; i++) { // Regular input arguments + // Convert ints to longs if required. + if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(i)->isa_int()) { + Node* int_as_long = _gvn.transform(new (C) ConvI2LNode(map()->in(i))); + call->init_req(cnt++, int_as_long); // long + call->init_req(cnt++, top()); // half + } else { + call->init_req(cnt++, map()->in(i)); + } + } call->init_req( cnt++, thread ); if( return_pc ) // Return PC, if asked for diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index a30fc80df39..2db3d7c0933 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -2692,27 +2692,38 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { _igvn.register_new_node_with_optimizer(store_value); } + if (CCallingConventionRequiresIntsAsLongs && + // See StubRoutines::select_fill_function for types. FLOAT has been converted to INT. + (t == T_FLOAT || t == T_INT || is_subword_type(t))) { + store_value = new (C) ConvI2LNode(store_value); + _igvn.register_new_node_with_optimizer(store_value); + } + Node* mem_phi = store->in(MemNode::Memory); Node* result_ctrl; Node* result_mem; const TypeFunc* call_type = OptoRuntime::array_fill_Type(); CallLeafNode *call = new (C) CallLeafNoFPNode(call_type, fill, fill_name, TypeAryPtr::get_array_body_type(t)); - call->init_req(TypeFunc::Parms+0, from); - call->init_req(TypeFunc::Parms+1, store_value); + uint cnt = 0; + call->init_req(TypeFunc::Parms + cnt++, from); + call->init_req(TypeFunc::Parms + cnt++, store_value); + if (CCallingConventionRequiresIntsAsLongs) { + call->init_req(TypeFunc::Parms + cnt++, C->top()); + } #ifdef _LP64 len = new (C) ConvI2LNode(len); _igvn.register_new_node_with_optimizer(len); #endif - call->init_req(TypeFunc::Parms+2, len); + call->init_req(TypeFunc::Parms + cnt++, len); #ifdef _LP64 - call->init_req(TypeFunc::Parms+3, C->top()); + call->init_req(TypeFunc::Parms + cnt++, C->top()); #endif - call->init_req( TypeFunc::Control, head->init_control()); - call->init_req( TypeFunc::I_O , C->top() ) ; // does no i/o - call->init_req( TypeFunc::Memory , mem_phi->in(LoopNode::EntryControl) ); - call->init_req( TypeFunc::ReturnAdr, C->start()->proj_out(TypeFunc::ReturnAdr) ); - call->init_req( TypeFunc::FramePtr, C->start()->proj_out(TypeFunc::FramePtr) ); + call->init_req(TypeFunc::Control, head->init_control()); + call->init_req(TypeFunc::I_O, C->top()); // Does no I/O. + call->init_req(TypeFunc::Memory, mem_phi->in(LoopNode::EntryControl)); + call->init_req(TypeFunc::ReturnAdr, C->start()->proj_out(TypeFunc::ReturnAdr)); + call->init_req(TypeFunc::FramePtr, C->start()->proj_out(TypeFunc::FramePtr)); _igvn.register_new_node_with_optimizer(call); result_ctrl = new (C) ProjNode(call,TypeFunc::Control); _igvn.register_new_node_with_optimizer(result_ctrl); diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 73f40e2d3e5..bd5d1370031 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -795,11 +795,20 @@ const TypeFunc* OptoRuntime::generic_arraycopy_Type() { const TypeFunc* OptoRuntime::array_fill_Type() { - // create input type (domain): pointer, int, size_t - const Type** fields = TypeTuple::fields(3 LP64_ONLY( + 1)); + const Type** fields; int argp = TypeFunc::Parms; - fields[argp++] = TypePtr::NOTNULL; - fields[argp++] = TypeInt::INT; + if (CCallingConventionRequiresIntsAsLongs) { + // create input type (domain): pointer, int, size_t + fields = TypeTuple::fields(3 LP64_ONLY( + 2)); + fields[argp++] = TypePtr::NOTNULL; + fields[argp++] = TypeLong::LONG; + fields[argp++] = Type::HALF; + } else { + // create input type (domain): pointer, int, size_t + fields = TypeTuple::fields(3 LP64_ONLY( + 1)); + fields[argp++] = TypePtr::NOTNULL; + fields[argp++] = TypeInt::INT; + } fields[argp++] = TypeX_X; // size in whatevers (size_t) LP64_ONLY(fields[argp++] = Type::HALF); // other half of long length const TypeTuple *domain = TypeTuple::make(argp, fields); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 32f045a9664..81210bebaa6 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -2714,6 +2714,71 @@ void SharedRuntime::get_utf(oopDesc* src, address dst) { } #endif // ndef HAVE_DTRACE_H +int SharedRuntime::convert_ints_to_longints_argcnt(int in_args_count, BasicType* in_sig_bt) { + int argcnt = in_args_count; + if (CCallingConventionRequiresIntsAsLongs) { + for (int in = 0; in < in_args_count; in++) { + BasicType bt = in_sig_bt[in]; + switch (bt) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + argcnt++; + break; + default: + break; + } + } + } else { + assert(0, "This should not be needed on this platform"); + } + + return argcnt; +} + +void SharedRuntime::convert_ints_to_longints(int i2l_argcnt, int& in_args_count, + BasicType*& in_sig_bt, VMRegPair*& in_regs) { + if (CCallingConventionRequiresIntsAsLongs) { + VMRegPair *new_in_regs = NEW_RESOURCE_ARRAY(VMRegPair, i2l_argcnt); + BasicType *new_in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); + + int argcnt = 0; + for (int in = 0; in < in_args_count; in++, argcnt++) { + BasicType bt = in_sig_bt[in]; + VMRegPair reg = in_regs[in]; + switch (bt) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + // Convert (bt) to (T_LONG,bt). + new_in_sig_bt[argcnt ] = T_LONG; + new_in_sig_bt[argcnt+1] = bt; + assert(reg.first()->is_valid() && !reg.second()->is_valid(), ""); + new_in_regs[argcnt ].set2(reg.first()); + new_in_regs[argcnt+1].set_bad(); + argcnt++; + break; + default: + // No conversion needed. + new_in_sig_bt[argcnt] = bt; + new_in_regs[argcnt] = reg; + break; + } + } + assert(argcnt == i2l_argcnt, "must match"); + + in_regs = new_in_regs; + in_sig_bt = new_in_sig_bt; + in_args_count = i2l_argcnt; + } else { + assert(0, "This should not be needed on this platform"); + } +} + // ------------------------------------------------------------------------- // Java-Java calling convention // (what you use when Java calls Java) diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 8ca5da3b53d..7e3abee63b5 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -366,6 +366,16 @@ class SharedRuntime: AllStatic { static int c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, VMRegPair *regs2, int total_args_passed); + // Compute the new number of arguments in the signature if 32 bit ints + // must be converted to longs. Needed if CCallingConventionRequiresIntsAsLongs + // is true. + static int convert_ints_to_longints_argcnt(int in_args_count, BasicType* in_sig_bt); + // Adapt a method's signature if it contains 32 bit integers that must + // be converted to longs. Needed if CCallingConventionRequiresIntsAsLongs + // is true. + static void convert_ints_to_longints(int i2l_argcnt, int& in_args_count, + BasicType*& in_sig_bt, VMRegPair*& in_regs); + // Generate I2C and C2I adapters. These adapters are simple argument marshalling // blobs. Unlike adapters in the tiger and earlier releases the code in these // blobs does not create a new frame and are therefore virtually invisible @@ -378,7 +388,7 @@ class SharedRuntime: AllStatic { // location for the interpreter to record. This is used by the frame code // to correct the sender code to match up with the stack pointer when the // thread left the compiled code. In addition it allows the interpreter - // to remove the space the c2i adapter allocated to do it argument conversion. + // to remove the space the c2i adapter allocated to do its argument conversion. // Although a c2i blob will always run interpreted even if compiled code is // present if we see that compiled code is present the compiled call site From 34c802394951fca1ee763c12025e2b337d7f6103 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 19 Sep 2013 17:31:42 +0200 Subject: [PATCH 023/265] 8024922: PPC64 (part 116): Extend adlc to generate fields into nodes Similar to specifying functions returning constants (as ins_avoid_back_to_back()) adlc now accepts specifications with prefix ins_field_xxx(tp) and adds field xxx of type tp to the node. Reviewed-by: kvn --- hotspot/src/share/vm/adlc/output_h.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 3fdaf39e8f1..8490109bfcc 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1539,7 +1539,20 @@ void ArchDesc::declareClasses(FILE *fp) { if ( instr->is_ideal_jump() ) { fprintf(fp, " GrowableArray _index2label;\n"); } - fprintf(fp,"public:\n"); + + fprintf(fp, "public:\n"); + + Attribute *att = instr->_attribs; + // Fields of the node specified in the ad file. + while (att != NULL) { + if (strncmp(att->_ident, "ins_field_", 10) == 0) { + const char *field_name = att->_ident+10; + const char *field_type = att->_val; + fprintf(fp, " %s _%s;\n", field_type, field_name); + } + att = (Attribute *)att->_next; + } + fprintf(fp," MachOper *opnd_array(uint operand_index) const {\n"); fprintf(fp," assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n"); fprintf(fp," return _opnd_array[operand_index];\n"); @@ -1586,8 +1599,9 @@ void ArchDesc::declareClasses(FILE *fp) { Attribute *attr = instr->_attribs; bool avoid_back_to_back = false; while (attr != NULL) { - if (strcmp(attr->_ident,"ins_cost") && - strcmp(attr->_ident,"ins_short_branch")) { + if (strcmp (attr->_ident,"ins_cost") && + strncmp(attr->_ident,"ins_field_", 10) != 0 && + strcmp (attr->_ident,"ins_short_branch")) { fprintf(fp," int %s() const { return %s; }\n", attr->_ident, attr->_val); } From 0732a739b30d4e11fb1e3cc13dbfc8e9e5b70c06 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Sun, 15 Sep 2013 15:28:58 +0200 Subject: [PATCH 024/265] 8024468: PPC64 (part 201): cppInterpreter: implement bytecode profiling Implement profiling for c2 jit compilation. Also enable new cppInterpreter features. Reviewed-by: kvn --- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 2 +- .../vm/interpreter/bytecodeInterpreter.cpp | 290 ++++++++++++----- .../bytecodeInterpreterProfiling.hpp | 308 ++++++++++++++++++ .../vm/interpreter/interpreterRuntime.cpp | 43 ++- .../vm/interpreter/interpreterRuntime.hpp | 19 +- .../vm/interpreter/invocationCounter.hpp | 22 +- hotspot/src/share/vm/oops/methodData.cpp | 5 + hotspot/src/share/vm/oops/methodData.hpp | 191 +++++++++++ .../vm/prims/jvmtiManageCapabilities.cpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 4 +- hotspot/src/share/vm/runtime/globals.hpp | 5 + 11 files changed, 790 insertions(+), 103 deletions(-) create mode 100644 hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 42e88a7374b..b1072b65de7 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -220,7 +220,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { } InvocationCounter *counter = mcs->invocation_counter(); counter->increment(); - if (counter->reached_InvocationLimit()) { + if (counter->reached_InvocationLimit(mcs->backedge_counter())) { CALL_VM_NOCHECK( InterpreterRuntime::frequency_counter_overflow(thread, NULL)); if (HAS_PENDING_EXCEPTION) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 0db00793e9a..6008fdd6e1c 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -28,6 +28,7 @@ #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/bytecodeInterpreter.inline.hpp" +#include "interpreter/bytecodeInterpreterProfiling.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "memory/resourceArea.hpp" @@ -142,19 +143,20 @@ * is no entry point to do the transition to vm so we just * do it by hand here. */ -#define VM_JAVA_ERROR_NO_JUMP(name, msg) \ +#define VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap) \ DECACHE_STATE(); \ SET_LAST_JAVA_FRAME(); \ { \ + InterpreterRuntime::note_a_trap(THREAD, istate->method(), BCI()); \ ThreadInVMfromJava trans(THREAD); \ Exceptions::_throw_msg(THREAD, __FILE__, __LINE__, name, msg); \ } \ RESET_LAST_JAVA_FRAME(); \ CACHE_STATE(); -// Normal throw of a java error -#define VM_JAVA_ERROR(name, msg) \ - VM_JAVA_ERROR_NO_JUMP(name, msg) \ +// Normal throw of a java error. +#define VM_JAVA_ERROR(name, msg, note_a_trap) \ + VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap) \ goto handle_exception; #ifdef PRODUCT @@ -340,9 +342,25 @@ if (UseLoopCounter) { \ bool do_OSR = UseOnStackReplacement; \ mcs->backedge_counter()->increment(); \ - if (do_OSR) do_OSR = mcs->backedge_counter()->reached_InvocationLimit(); \ + if (ProfileInterpreter) { \ + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); \ + /* Check for overflow against MDO count. */ \ + do_OSR = do_OSR \ + && (mdo_last_branch_taken_count >= (uint)InvocationCounter::InterpreterBackwardBranchLimit)\ + /* When ProfileInterpreter is on, the backedge_count comes */ \ + /* from the methodDataOop, which value does not get reset on */ \ + /* the call to frequency_counter_overflow(). To avoid */ \ + /* excessive calls to the overflow routine while the method is */ \ + /* being compiled, add a second test to make sure the overflow */ \ + /* function is called only once every overflow_frequency. */ \ + && (!(mdo_last_branch_taken_count & 1023)); \ + } else { \ + /* check for overflow of backedge counter */ \ + do_OSR = do_OSR \ + && mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter()); \ + } \ if (do_OSR) { \ - nmethod* osr_nmethod; \ + nmethod* osr_nmethod; \ OSR_REQUEST(osr_nmethod, branch_pc); \ if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \ intptr_t* buf; \ @@ -355,7 +373,6 @@ } \ } \ } /* UseCompiler ... */ \ - mcs->invocation_counter()->increment(); \ SAFEPOINT; \ } @@ -388,17 +405,21 @@ #undef CACHE_FRAME #define CACHE_FRAME() +// BCI() returns the current bytecode-index. +#undef BCI +#define BCI() ((int)(intptr_t)(pc - (intptr_t)istate->method()->code_base())) + /* * CHECK_NULL - Macro for throwing a NullPointerException if the object * passed is a null ref. * On some architectures/platforms it should be possible to do this implicitly */ #undef CHECK_NULL -#define CHECK_NULL(obj_) \ - if ((obj_) == NULL) { \ - VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), ""); \ - } \ - VERIFY_OOP(obj_) +#define CHECK_NULL(obj_) \ + if ((obj_) == NULL) { \ + VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap); \ + } \ + VERIFY_OOP(obj_) #define VMdoubleConstZero() 0.0 #define VMdoubleConstOne() 1.0 @@ -635,9 +656,16 @@ BytecodeInterpreter::run(interpreterState istate) { topOfStack < istate->stack_base(), "Stack top out of range"); +#ifdef CC_INTERP_PROFILE + // MethodData's last branch taken count. + uint mdo_last_branch_taken_count = 0; +#else + const uint mdo_last_branch_taken_count = 0; +#endif + switch (istate->msg()) { case initialize: { - if (initialized++) ShouldNotReachHere(); // Only one initialize call + if (initialized++) ShouldNotReachHere(); // Only one initialize call. _compiling = (UseCompiler || CountCompiledCalls); #ifdef VM_JVMTI _jvmti_interp_events = JvmtiExport::can_post_interpreter_events(); @@ -656,15 +684,12 @@ BytecodeInterpreter::run(interpreterState istate) { METHOD->increment_interpreter_invocation_count(THREAD); } mcs->invocation_counter()->increment(); - if (mcs->invocation_counter()->reached_InvocationLimit()) { - CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception); - - // We no longer retry on a counter overflow - - // istate->set_msg(retry_method); - // THREAD->clr_do_not_unlock(); - // return; + if (mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter())) { + CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception); + // We no longer retry on a counter overflow. } + // Get or create profile data. Check for pending (async) exceptions. + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); SAFEPOINT; } @@ -686,8 +711,7 @@ BytecodeInterpreter::run(interpreterState istate) { } #endif // HACK - - // lock method if synchronized + // Lock method if synchronized. if (METHOD->is_synchronized()) { // oop rcvr = locals[0].j.r; oop rcvr; @@ -697,7 +721,7 @@ BytecodeInterpreter::run(interpreterState istate) { rcvr = LOCALS_OBJECT(0); VERIFY_OOP(rcvr); } - // The initial monitor is ours for the taking + // The initial monitor is ours for the taking. // Monitor not filled in frame manager any longer as this caused race condition with biased locking. BasicObjectLock* mon = &istate->monitor_base()[-1]; mon->set_obj(rcvr); @@ -803,6 +827,12 @@ BytecodeInterpreter::run(interpreterState istate) { // clear the message so we don't confuse ourselves later assert(THREAD->pop_frame_in_process(), "wrong frame pop state"); istate->set_msg(no_request); + if (_compiling) { + // Set MDX back to the ProfileData of the invoke bytecode that will be + // restarted. + SET_MDX(NULL); + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); + } THREAD->clr_pop_frame_in_process(); goto run; } @@ -836,6 +866,11 @@ BytecodeInterpreter::run(interpreterState istate) { if (THREAD->has_pending_exception()) goto handle_exception; // Update the pc by the saved amount of the invoke bytecode size UPDATE_PC(istate->bcp_advance()); + + if (_compiling) { + // Get or create profile data. Check for pending (async) exceptions. + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); + } goto run; } @@ -843,6 +878,11 @@ BytecodeInterpreter::run(interpreterState istate) { // Returned from an opcode that will reexecute. Deopt was // a result of a PopFrame request. // + + if (_compiling) { + // Get or create profile data. Check for pending (async) exceptions. + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); + } goto run; } @@ -865,6 +905,11 @@ BytecodeInterpreter::run(interpreterState istate) { } UPDATE_PC(Bytecodes::length_at(METHOD, pc)); if (THREAD->has_pending_exception()) goto handle_exception; + + if (_compiling) { + // Get or create profile data. Check for pending (async) exceptions. + BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception); + } goto run; } case got_monitors: { @@ -1115,6 +1160,11 @@ run: uint16_t reg = Bytes::get_Java_u2(pc + 2); opcode = pc[1]; + + // Wide and it's sub-bytecode are counted as separate instructions. If we + // don't account for this here, the bytecode trace skips the next bytecode. + DO_UPDATE_INSTRUCTION_COUNT(opcode); + switch(opcode) { case Bytecodes::_aload: VERIFY_OOP(LOCALS_OBJECT(reg)); @@ -1158,10 +1208,13 @@ run: UPDATE_PC_AND_CONTINUE(6); } case Bytecodes::_ret: + // Profile ret. + BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(reg)))); + // Now, update the pc. pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(reg)); UPDATE_PC_AND_CONTINUE(0); default: - VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode"); + VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode", note_no_trap); } } @@ -1242,7 +1295,7 @@ run: CASE(_i##opcname): \ if (test && (STACK_INT(-1) == 0)) { \ VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \ - "/ by zero"); \ + "/ by zero", note_div0Check_trap); \ } \ SET_STACK_INT(VMint##opname(STACK_INT(-2), \ STACK_INT(-1)), \ @@ -1254,7 +1307,7 @@ run: jlong l1 = STACK_LONG(-1); \ if (VMlongEqz(l1)) { \ VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \ - "/ by long zero"); \ + "/ by long zero", note_div0Check_trap); \ } \ } \ /* First long at (-1,-2) next long at (-3,-4) */ \ @@ -1467,17 +1520,23 @@ run: #define COMPARISON_OP(name, comparison) \ CASE(_if_icmp##name): { \ - int skip = (STACK_INT(-2) comparison STACK_INT(-1)) \ + const bool cmp = (STACK_INT(-2) comparison STACK_INT(-1)); \ + int skip = cmp \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ + /* Profile branch. */ \ + BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -2); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ } \ CASE(_if##name): { \ - int skip = (STACK_INT(-1) comparison 0) \ + const bool cmp = (STACK_INT(-1) comparison 0); \ + int skip = cmp \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ + /* Profile branch. */ \ + BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1486,9 +1545,12 @@ run: #define COMPARISON_OP2(name, comparison) \ COMPARISON_OP(name, comparison) \ CASE(_if_acmp##name): { \ - int skip = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1)) \ + const bool cmp = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1)); \ + int skip = cmp \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ + /* Profile branch. */ \ + BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -2); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1496,9 +1558,12 @@ run: #define NULL_COMPARISON_NOT_OP(name) \ CASE(_if##name): { \ - int skip = (!(STACK_OBJECT(-1) == NULL)) \ + const bool cmp = (!(STACK_OBJECT(-1) == NULL)); \ + int skip = cmp \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ + /* Profile branch. */ \ + BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1506,9 +1571,12 @@ run: #define NULL_COMPARISON_OP(name) \ CASE(_if##name): { \ - int skip = ((STACK_OBJECT(-1) == NULL)) \ + const bool cmp = ((STACK_OBJECT(-1) == NULL)); \ + int skip = cmp \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ + /* Profile branch. */ \ + BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \ UPDATE_PC_AND_TOS(skip, -1); \ DO_BACKEDGE_CHECKS(skip, branch_pc); \ CONTINUE; \ @@ -1531,30 +1599,42 @@ run: int32_t high = Bytes::get_Java_u4((address)&lpc[2]); int32_t skip; key -= low; - skip = ((uint32_t) key > (uint32_t)(high - low)) - ? Bytes::get_Java_u4((address)&lpc[0]) - : Bytes::get_Java_u4((address)&lpc[key + 3]); - // Does this really need a full backedge check (osr?) + if (((uint32_t) key > (uint32_t)(high - low))) { + key = -1; + skip = Bytes::get_Java_u4((address)&lpc[0]); + } else { + skip = Bytes::get_Java_u4((address)&lpc[key + 3]); + } + // Profile switch. + BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/key); + // Does this really need a full backedge check (osr)? address branch_pc = pc; UPDATE_PC_AND_TOS(skip, -1); DO_BACKEDGE_CHECKS(skip, branch_pc); CONTINUE; } - /* Goto pc whose table entry matches specified key */ + /* Goto pc whose table entry matches specified key. */ CASE(_lookupswitch): { jint* lpc = (jint*)VMalignWordUp(pc+1); int32_t key = STACK_INT(-1); int32_t skip = Bytes::get_Java_u4((address) lpc); /* default amount */ + // Remember index. + int index = -1; + int newindex = 0; int32_t npairs = Bytes::get_Java_u4((address) &lpc[1]); while (--npairs >= 0) { - lpc += 2; - if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) { - skip = Bytes::get_Java_u4((address)&lpc[1]); - break; - } + lpc += 2; + if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) { + skip = Bytes::get_Java_u4((address)&lpc[1]); + index = newindex; + break; + } + newindex += 1; } + // Profile switch. + BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/index); address branch_pc = pc; UPDATE_PC_AND_TOS(skip, -1); DO_BACKEDGE_CHECKS(skip, branch_pc); @@ -1639,7 +1719,7 @@ run: if ((uint32_t)index >= (uint32_t)arrObj->length()) { \ sprintf(message, "%d", index); \ VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \ - message); \ + message, note_rangeCheck_trap); \ } /* 32-bit loads. These handle conversion from < 32-bit types */ @@ -1713,15 +1793,22 @@ run: // arrObj, index are set if (rhsObject != NULL) { /* Check assignability of rhsObject into arrObj */ - Klass* rhsKlassOop = rhsObject->klass(); // EBX (subclass) - Klass* elemKlassOop = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX + Klass* rhsKlass = rhsObject->klass(); // EBX (subclass) + Klass* elemKlass = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX // // Check for compatibilty. This check must not GC!! // Seems way more expensive now that we must dispatch // - if (rhsKlassOop != elemKlassOop && !rhsKlassOop->is_subtype_of(elemKlassOop)) { // ebx->is... - VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), ""); + if (rhsKlass != elemKlass && !rhsKlass->is_subtype_of(elemKlass)) { // ebx->is... + // Decrement counter if subtype check failed. + BI_PROFILE_SUBTYPECHECK_FAILED(rhsKlass); + VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "", note_arrayCheck_trap); } + // Profile checkcast with null_seen and receiver. + BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, rhsKlass); + } else { + // Profile checkcast with null_seen and receiver. + BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL); } ((objArrayOopDesc *) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); @@ -2119,10 +2206,14 @@ run: if (UseTLAB) { result = (oop) THREAD->tlab().allocate(obj_size); } + // Disable non-TLAB-based fast-path, because profiling requires that all + // allocations go through InterpreterRuntime::_new() if THREAD->tlab().allocate + // returns NULL. +#ifndef CC_INTERP_PROFILE if (result == NULL) { need_zero = true; // Try allocate in shared eden - retry: + retry: HeapWord* compare_to = *Universe::heap()->top_addr(); HeapWord* new_top = compare_to + obj_size; if (new_top <= *Universe::heap()->end_addr()) { @@ -2132,6 +2223,7 @@ run: result = (oop) compare_to; } } +#endif if (result != NULL) { // Initialize object (if nonzero size and need) and then the header if (need_zero ) { @@ -2187,61 +2279,63 @@ run: if (STACK_OBJECT(-1) != NULL) { VERIFY_OOP(STACK_OBJECT(-1)); u2 index = Bytes::get_Java_u2(pc+1); - if (ProfileInterpreter) { - // needs Profile_checkcast QQQ - ShouldNotReachHere(); - } // Constant pool may have actual klass or unresolved klass. If it is - // unresolved we must resolve it + // unresolved we must resolve it. if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass(); - Klass* objKlassOop = STACK_OBJECT(-1)->klass(); //ebx + Klass* objKlass = STACK_OBJECT(-1)->klass(); // ebx // // Check for compatibilty. This check must not GC!! - // Seems way more expensive now that we must dispatch + // Seems way more expensive now that we must dispatch. // - if (objKlassOop != klassOf && - !objKlassOop->is_subtype_of(klassOf)) { + if (objKlass != klassOf && !objKlass->is_subtype_of(klassOf)) { + // Decrement counter at checkcast. + BI_PROFILE_SUBTYPECHECK_FAILED(objKlass); ResourceMark rm(THREAD); - const char* objName = objKlassOop->external_name(); + const char* objName = objKlass->external_name(); const char* klassName = klassOf->external_name(); char* message = SharedRuntime::generate_class_cast_message( objName, klassName); - VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message); + VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap); } + // Profile checkcast with null_seen and receiver. + BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, objKlass); } else { - if (UncommonNullCast) { -// istate->method()->set_null_cast_seen(); -// [RGV] Not sure what to do here! - - } + // Profile checkcast with null_seen and receiver. + BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL); } UPDATE_PC_AND_CONTINUE(3); CASE(_instanceof): if (STACK_OBJECT(-1) == NULL) { SET_STACK_INT(0, -1); + // Profile instanceof with null_seen and receiver. + BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/true, NULL); } else { VERIFY_OOP(STACK_OBJECT(-1)); u2 index = Bytes::get_Java_u2(pc+1); // Constant pool may have actual klass or unresolved klass. If it is - // unresolved we must resolve it + // unresolved we must resolve it. if (METHOD->constants()->tag_at(index).is_unresolved_klass()) { CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception); } Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass(); - Klass* objKlassOop = STACK_OBJECT(-1)->klass(); + Klass* objKlass = STACK_OBJECT(-1)->klass(); // // Check for compatibilty. This check must not GC!! - // Seems way more expensive now that we must dispatch + // Seems way more expensive now that we must dispatch. // - if ( objKlassOop == klassOf || objKlassOop->is_subtype_of(klassOf)) { + if ( objKlass == klassOf || objKlass->is_subtype_of(klassOf)) { SET_STACK_INT(1, -1); } else { SET_STACK_INT(0, -1); + // Decrement counter at checkcast. + BI_PROFILE_SUBTYPECHECK_FAILED(objKlass); } + // Profile instanceof with null_seen and receiver. + BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/false, objKlass); } UPDATE_PC_AND_CONTINUE(3); @@ -2384,6 +2478,9 @@ run: istate->set_callee_entry_point(method->from_interpreted_entry()); istate->set_bcp_advance(5); + // Invokedynamic has got a call counter, just like an invokestatic -> increment! + BI_PROFILE_UPDATE_CALL(); + UPDATE_PC_AND_RETURN(0); // I'll be back... } @@ -2416,6 +2513,9 @@ run: istate->set_callee_entry_point(method->from_interpreted_entry()); istate->set_bcp_advance(3); + // Invokehandle has got a call counter, just like a final call -> increment! + BI_PROFILE_UPDATE_FINALCALL(); + UPDATE_PC_AND_RETURN(0); // I'll be back... } @@ -2443,14 +2543,18 @@ run: CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); if (cache->is_vfinal()) { callee = cache->f2_as_vfinal_method(); + // Profile 'special case of invokeinterface' final call. + BI_PROFILE_UPDATE_FINALCALL(); } else { - // get receiver + // Get receiver. int parms = cache->parameter_size(); - // Same comments as invokevirtual apply here - VERIFY_OOP(STACK_OBJECT(-parms)); - InstanceKlass* rcvrKlass = (InstanceKlass*) - STACK_OBJECT(-parms)->klass(); + // Same comments as invokevirtual apply here. + oop rcvr = STACK_OBJECT(-parms); + VERIFY_OOP(rcvr); + InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; + // Profile 'special case of invokeinterface' virtual call. + BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); } istate->set_callee(callee); istate->set_callee_entry_point(callee->from_interpreted_entry()); @@ -2481,15 +2585,18 @@ run: // interface. The link resolver checks this but only for the first // time this interface is called. if (i == int2->itable_length()) { - VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), ""); + VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap); } int mindex = cache->f2_as_index(); itableMethodEntry* im = ki->first_method_entry(rcvr->klass()); callee = im[mindex].method(); if (callee == NULL) { - VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), ""); + VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), "", note_no_trap); } + // Profile virtual call. + BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); + istate->set_callee(callee); istate->set_callee_entry_point(callee->from_interpreted_entry()); #ifdef VM_JVMTI @@ -2521,8 +2628,11 @@ run: Method* callee; if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) { CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); - if (cache->is_vfinal()) callee = cache->f2_as_vfinal_method(); - else { + if (cache->is_vfinal()) { + callee = cache->f2_as_vfinal_method(); + // Profile final call. + BI_PROFILE_UPDATE_FINALCALL(); + } else { // get receiver int parms = cache->parameter_size(); // this works but needs a resourcemark and seems to create a vtable on every call: @@ -2531,8 +2641,9 @@ run: // this fails with an assert // InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass()); // but this works - VERIFY_OOP(STACK_OBJECT(-parms)); - InstanceKlass* rcvrKlass = (InstanceKlass*) STACK_OBJECT(-parms)->klass(); + oop rcvr = STACK_OBJECT(-parms); + VERIFY_OOP(rcvr); + InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); /* Executing this code in java.lang.String: public String(char value[]) { @@ -2550,12 +2661,17 @@ run: */ callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; + // Profile virtual call. + BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); } } else { if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) { CHECK_NULL(STACK_OBJECT(-(cache->parameter_size()))); } callee = cache->f1_as_method(); + + // Profile call. + BI_PROFILE_UPDATE_CALL(); } istate->set_callee(callee); @@ -2607,6 +2723,8 @@ run: CASE(_goto): { int16_t offset = (int16_t)Bytes::get_Java_u2(pc + 1); + // Profile jump. + BI_PROFILE_UPDATE_JUMP(); address branch_pc = pc; UPDATE_PC(offset); DO_BACKEDGE_CHECKS(offset, branch_pc); @@ -2623,6 +2741,8 @@ run: CASE(_goto_w): { int32_t offset = Bytes::get_Java_u4(pc + 1); + // Profile jump. + BI_PROFILE_UPDATE_JUMP(); address branch_pc = pc; UPDATE_PC(offset); DO_BACKEDGE_CHECKS(offset, branch_pc); @@ -2632,6 +2752,9 @@ run: /* return from a jsr or jsr_w */ CASE(_ret): { + // Profile ret. + BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(pc[1])))); + // Now, update the pc. pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(pc[1])); UPDATE_PC_AND_CONTINUE(0); } @@ -2713,6 +2836,9 @@ run: } // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort(except_oop)); + + // Update profiling data. + BI_PROFILE_ALIGN_TO_CURRENT_BCI(); goto run; } if (TraceExceptions) { @@ -2920,7 +3046,7 @@ run: oop rcvr = base->obj(); if (rcvr == NULL) { if (!suppress_error) { - VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), ""); + VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap); illegal_state_oop = THREAD->pending_exception(); THREAD->clear_pending_exception(); } @@ -3008,9 +3134,9 @@ run: // A pending exception that was pending prior to a possible popping frame // overrides the popping frame. // - assert(!suppress_error || suppress_error && illegal_state_oop() == NULL, "Error was not suppressed"); + assert(!suppress_error || (suppress_error && illegal_state_oop() == NULL), "Error was not suppressed"); if (illegal_state_oop() != NULL || original_exception() != NULL) { - // inform the frame manager we have no result + // Inform the frame manager we have no result. istate->set_msg(throwing_exception); if (illegal_state_oop() != NULL) THREAD->set_pending_exception(illegal_state_oop(), NULL, 0); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp new file mode 100644 index 00000000000..095a989cc01 --- /dev/null +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 file defines a set of macros which are used by the c++-interpreter +// for updating a method's methodData object. + + +#ifndef SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP +#define SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP + + +// Global settings ///////////////////////////////////////////////////////////// + + +// Enables profiling support. +#if defined(COMPILER2) +#define CC_INTERP_PROFILE +#endif + +// Enables assertions for profiling code (also works in product-builds). +// #define CC_INTERP_PROFILE_WITH_ASSERTIONS + + +#ifdef CC_INTERP + +// Empty dummy implementations if profiling code is switched off. ////////////// + +#ifndef CC_INTERP_PROFILE + +#define SET_MDX(mdx) + +#define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler) \ + if (ProfileInterpreter) { \ + ShouldNotReachHere(); \ + } + +#define BI_PROFILE_ALIGN_TO_CURRENT_BCI() + +#define BI_PROFILE_UPDATE_JUMP() +#define BI_PROFILE_UPDATE_BRANCH(is_taken) +#define BI_PROFILE_UPDATE_RET(bci) +#define BI_PROFILE_SUBTYPECHECK_FAILED(receiver) +#define BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver) +#define BI_PROFILE_UPDATE_INSTANCEOF(null_seen, receiver) +#define BI_PROFILE_UPDATE_CALL() +#define BI_PROFILE_UPDATE_FINALCALL() +#define BI_PROFILE_UPDATE_VIRTUALCALL(receiver) +#define BI_PROFILE_UPDATE_SWITCH(switch_index) + + +#else + + +// Non-dummy implementations /////////////////////////////////////////////////// + +// Accessors for the current method data pointer 'mdx'. +#define MDX() (istate->mdx()) +#define SET_MDX(mdx) \ + if (TraceProfileInterpreter) { \ + /* Let it look like TraceBytecodes' format. */ \ + tty->print_cr("[%d] %4d " \ + "mdx " PTR_FORMAT "(%d)" \ + " " \ + " \t-> " PTR_FORMAT "(%d)", \ + (int) THREAD->osthread()->thread_id(), \ + BCI(), \ + MDX(), \ + (MDX() == NULL \ + ? 0 \ + : istate->method()->method_data()->dp_to_di((address)MDX())), \ + mdx, \ + istate->method()->method_data()->dp_to_di((address)mdx) \ + ); \ + }; \ + istate->set_mdx(mdx); + + +// Dumps the profiling method data for the current method. +#ifdef PRODUCT +#define BI_PROFILE_PRINT_METHOD_DATA() +#else // PRODUCT +#define BI_PROFILE_PRINT_METHOD_DATA() \ + { \ + ttyLocker ttyl; \ + MethodData *md = istate->method()->method_data(); \ + tty->cr(); \ + tty->print("method data at mdx " PTR_FORMAT "(0) for", \ + md->data_layout_at(md->bci_to_di(0))); \ + istate->method()->print_short_name(tty); \ + tty->cr(); \ + if (md != NULL) { \ + md->print_data_on(tty); \ + address mdx = (address) MDX(); \ + if (mdx != NULL) { \ + tty->print_cr("current mdx " PTR_FORMAT "(%d)", \ + mdx, \ + istate->method()->method_data()->dp_to_di(mdx)); \ + } \ + } else { \ + tty->print_cr("no method data"); \ + } \ + } +#endif // PRODUCT + + +// Gets or creates the profiling method data and initializes mdx. +#define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler) \ + if (ProfileInterpreter && MDX() == NULL) { \ + /* Mdx is not yet initialized for this activation. */ \ + MethodData *md = istate->method()->method_data(); \ + if (md == NULL) { \ + MethodCounters* mcs; \ + GET_METHOD_COUNTERS(mcs); \ + /* The profiling method data doesn't exist for this method, */ \ + /* create it if the counters have overflowed. */ \ + if (mcs->invocation_counter() \ + ->reached_ProfileLimit(mcs->backedge_counter())) { \ + /* Must use CALL_VM, because an async exception may be pending. */ \ + CALL_VM((InterpreterRuntime::profile_method(THREAD)), \ + exception_handler); \ + md = istate->method()->method_data(); \ + if (md != NULL) { \ + if (TraceProfileInterpreter) { \ + BI_PROFILE_PRINT_METHOD_DATA(); \ + } \ + Method *m = istate->method(); \ + int bci = m->bci_from(pc); \ + jint di = md->bci_to_di(bci); \ + SET_MDX(md->data_layout_at(di)); \ + } \ + } \ + } else { \ + /* The profiling method data exists, align the method data pointer */ \ + /* mdx to the current bytecode index. */ \ + if (TraceProfileInterpreter) { \ + BI_PROFILE_PRINT_METHOD_DATA(); \ + } \ + SET_MDX(md->data_layout_at(md->bci_to_di(BCI()))); \ + } \ + } + + +// Asserts that the current method data pointer mdx corresponds +// to the current bytecode. +#if defined(CC_INTERP_PROFILE_WITH_ASSERTIONS) +#define BI_PROFILE_CHECK_MDX() \ + { \ + MethodData *md = istate->method()->method_data(); \ + address mdx = (address) MDX(); \ + address mdx2 = (address) md->data_layout_at(md->bci_to_di(BCI())); \ + guarantee(md != NULL, "1"); \ + guarantee(mdx != NULL, "2"); \ + guarantee(mdx2 != NULL, "3"); \ + if (mdx != mdx2) { \ + BI_PROFILE_PRINT_METHOD_DATA(); \ + fatal3("invalid mdx at bci %d:" \ + " was " PTR_FORMAT \ + " but expected " PTR_FORMAT, \ + BCI(), \ + mdx, \ + mdx2); \ + } \ + } +#else +#define BI_PROFILE_CHECK_MDX() +#endif + + +// Aligns the method data pointer mdx to the current bytecode index. +#define BI_PROFILE_ALIGN_TO_CURRENT_BCI() \ + if (ProfileInterpreter && MDX() != NULL) { \ + MethodData *md = istate->method()->method_data(); \ + SET_MDX(md->data_layout_at(md->bci_to_di(BCI()))); \ + } + + +// Updates profiling data for a jump. +#define BI_PROFILE_UPDATE_JUMP() \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + JumpData::increment_taken_count_no_overflow(MDX()); \ + /* Remember last branch taken count. */ \ + mdo_last_branch_taken_count = JumpData::taken_count(MDX()); \ + SET_MDX(JumpData::advance_taken(MDX())); \ + } + + +// Updates profiling data for a taken/not taken branch. +#define BI_PROFILE_UPDATE_BRANCH(is_taken) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + if (is_taken) { \ + BranchData::increment_taken_count_no_overflow(MDX()); \ + /* Remember last branch taken count. */ \ + mdo_last_branch_taken_count = BranchData::taken_count(MDX()); \ + SET_MDX(BranchData::advance_taken(MDX())); \ + } else { \ + BranchData::increment_not_taken_count_no_overflow(MDX()); \ + SET_MDX(BranchData::advance_not_taken(MDX())); \ + } \ + } + + +// Updates profiling data for a ret with given bci. +#define BI_PROFILE_UPDATE_RET(bci) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + MethodData *md = istate->method()->method_data(); \ +/* FIXME: there is more to do here than increment and advance(mdx)! */ \ + CounterData::increment_count_no_overflow(MDX()); \ + SET_MDX(RetData::advance(md, bci)); \ + } + +// Decrement counter at checkcast if the subtype check fails (as template +// interpreter does!). +#define BI_PROFILE_SUBTYPECHECK_FAILED(receiver) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver); \ + ReceiverTypeData::decrement_count(MDX()); \ + } + +// Updates profiling data for a checkcast (was a null seen? which receiver?). +#define BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + if (null_seen) { \ + ReceiverTypeData::set_null_seen(MDX()); \ + } else { \ + /* Template interpreter doesn't increment count. */ \ + /* ReceiverTypeData::increment_count_no_overflow(MDX()); */ \ + ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver); \ + } \ + SET_MDX(ReceiverTypeData::advance(MDX())); \ + } + + +// Updates profiling data for an instanceof (was a null seen? which receiver?). +#define BI_PROFILE_UPDATE_INSTANCEOF(null_seen, receiver) \ + BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver) + + +// Updates profiling data for a call. +#define BI_PROFILE_UPDATE_CALL() \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + CounterData::increment_count_no_overflow(MDX()); \ + SET_MDX(CounterData::advance(MDX())); \ + } + + +// Updates profiling data for a final call. +#define BI_PROFILE_UPDATE_FINALCALL() \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + VirtualCallData::increment_count_no_overflow(MDX()); \ + SET_MDX(VirtualCallData::advance(MDX())); \ + } + + +// Updates profiling data for a virtual call with given receiver Klass. +#define BI_PROFILE_UPDATE_VIRTUALCALL(receiver) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + VirtualCallData::increment_receiver_count_no_overflow(MDX(), receiver); \ + SET_MDX(VirtualCallData::advance(MDX())); \ + } + + +// Updates profiling data for a switch (tabelswitch or lookupswitch) with +// given taken index (-1 means default case was taken). +#define BI_PROFILE_UPDATE_SWITCH(switch_index) \ + if (ProfileInterpreter && MDX() != NULL) { \ + BI_PROFILE_CHECK_MDX(); \ + MultiBranchData::increment_count_no_overflow(MDX(), switch_index); \ + SET_MDX(MultiBranchData::advance(MDX(), switch_index)); \ + } + + +// The end ///////////////////////////////////////////////////////////////////// + +#endif // CC_INTERP_PROFILE + +#endif // CC_INTERP + +#endif // SHARE_VM_INTERPRETER_BYTECODECINTERPRETERPROFILING_HPP diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 4a3019f867f..d57fc75498e 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -241,18 +241,15 @@ IRT_END //------------------------------------------------------------------------------------------------------------------------ // Exceptions -// Assume the compiler is (or will be) interested in this event. -// If necessary, create an MDO to hold the information, and record it. -void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) { - assert(ProfileTraps, "call me only if profiling"); - methodHandle trap_method(thread, method(thread)); - +void InterpreterRuntime::note_trap_inner(JavaThread* thread, int reason, + methodHandle trap_method, int trap_bci, TRAPS) { if (trap_method.not_null()) { MethodData* trap_mdo = trap_method->method_data(); if (trap_mdo == NULL) { Method::build_interpreter_method_data(trap_method, THREAD); if (HAS_PENDING_EXCEPTION) { - assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); + assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), + "we expect only an OOM error here"); CLEAR_PENDING_EXCEPTION; } trap_mdo = trap_method->method_data(); @@ -261,12 +258,42 @@ void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) { if (trap_mdo != NULL) { // Update per-method count of trap events. The interpreter // is updating the MDO to simulate the effect of compiler traps. - int trap_bci = trap_method->bci_from(bcp(thread)); Deoptimization::update_method_data_from_interpreter(trap_mdo, trap_bci, reason); } } } +// Assume the compiler is (or will be) interested in this event. +// If necessary, create an MDO to hold the information, and record it. +void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) { + assert(ProfileTraps, "call me only if profiling"); + methodHandle trap_method(thread, method(thread)); + int trap_bci = trap_method->bci_from(bcp(thread)); + note_trap_inner(thread, reason, trap_method, trap_bci, THREAD); +} + +#ifdef CC_INTERP +// As legacy note_trap, but we have more arguments. +IRT_ENTRY(void, InterpreterRuntime::note_trap(JavaThread* thread, int reason, Method *method, int trap_bci)) + methodHandle trap_method(method); + note_trap_inner(thread, reason, trap_method, trap_bci, THREAD); +IRT_END + +// Class Deoptimization is not visible in BytecodeInterpreter, so we need a wrapper +// for each exception. +void InterpreterRuntime::note_nullCheck_trap(JavaThread* thread, Method *method, int trap_bci) + { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_null_check, method, trap_bci); } +void InterpreterRuntime::note_div0Check_trap(JavaThread* thread, Method *method, int trap_bci) + { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_div0_check, method, trap_bci); } +void InterpreterRuntime::note_rangeCheck_trap(JavaThread* thread, Method *method, int trap_bci) + { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_range_check, method, trap_bci); } +void InterpreterRuntime::note_classCheck_trap(JavaThread* thread, Method *method, int trap_bci) + { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_class_check, method, trap_bci); } +void InterpreterRuntime::note_arrayCheck_trap(JavaThread* thread, Method *method, int trap_bci) + { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_array_check, method, trap_bci); } +#endif // CC_INTERP + + static Handle get_preinitialized_exception(Klass* k, TRAPS) { // get klass InstanceKlass* klass = InstanceKlass::cast(k); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index ad44210ef4d..1fa6789dc5c 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -66,9 +66,15 @@ class InterpreterRuntime: AllStatic { static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); } static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); } + static void note_trap_inner(JavaThread* thread, int reason, + methodHandle trap_method, int trap_bci, TRAPS); static void note_trap(JavaThread *thread, int reason, TRAPS); +#ifdef CC_INTERP + // Profile traps in C++ interpreter. + static void note_trap(JavaThread* thread, int reason, Method *method, int trap_bci); +#endif // CC_INTERP - // Inner work method for Interpreter's frequency counter overflow + // Inner work method for Interpreter's frequency counter overflow. static nmethod* frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp); public: @@ -100,6 +106,17 @@ class InterpreterRuntime: AllStatic { #endif static void throw_pending_exception(JavaThread* thread); +#ifdef CC_INTERP + // Profile traps in C++ interpreter. + static void note_nullCheck_trap (JavaThread* thread, Method *method, int trap_bci); + static void note_div0Check_trap (JavaThread* thread, Method *method, int trap_bci); + static void note_rangeCheck_trap(JavaThread* thread, Method *method, int trap_bci); + static void note_classCheck_trap(JavaThread* thread, Method *method, int trap_bci); + static void note_arrayCheck_trap(JavaThread* thread, Method *method, int trap_bci); + // A dummy for makros that shall not profile traps. + static void note_no_trap(JavaThread* thread, Method *method, int trap_bci) {} +#endif // CC_INTERP + // Statics & fields static void resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode); diff --git a/hotspot/src/share/vm/interpreter/invocationCounter.hpp b/hotspot/src/share/vm/interpreter/invocationCounter.hpp index db896d8ade6..e0cb50cbe09 100644 --- a/hotspot/src/share/vm/interpreter/invocationCounter.hpp +++ b/hotspot/src/share/vm/interpreter/invocationCounter.hpp @@ -99,16 +99,24 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC { int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } int get_ProfileLimit() const { return InterpreterProfileLimit >> number_of_noncount_bits; } +#ifdef CC_INTERP // Test counter using scaled limits like the asm interpreter would do rather than doing // the shifts to normalize the counter. - - bool reached_InvocationLimit() const { return _counter >= (unsigned int) InterpreterInvocationLimit; } - bool reached_BackwardBranchLimit() const { return _counter >= (unsigned int) InterpreterBackwardBranchLimit; } - - // Do this just like asm interpreter does for max speed - bool reached_ProfileLimit(InvocationCounter *back_edge_count) const { - return (_counter && count_mask) + back_edge_count->_counter >= (unsigned int) InterpreterProfileLimit; + // Checks sum of invocation_counter and backedge_counter as the template interpreter does. + bool reached_InvocationLimit(InvocationCounter *back_edge_count) const { + return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= + (unsigned int) InterpreterInvocationLimit; } + bool reached_BackwardBranchLimit(InvocationCounter *back_edge_count) const { + return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= + (unsigned int) InterpreterBackwardBranchLimit; + } + // Do this just like asm interpreter does for max speed. + bool reached_ProfileLimit(InvocationCounter *back_edge_count) const { + return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= + (unsigned int) InterpreterProfileLimit; + } +#endif // CC_INTERP void increment() { _counter += count_increment; } diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 89a4cd4aa6b..a3b485a2bd8 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -244,6 +244,11 @@ address RetData::fixup_ret(int return_bci, MethodData* h_mdo) { return mdp; } +#ifdef CC_INTERP +DataLayout* RetData::advance(MethodData *md, int bci) { + return (DataLayout*) md->bci_to_dp(bci); +} +#endif // CC_INTERP #ifndef PRODUCT void RetData::print_data_on(outputStream* st) { diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 765b91c142c..b74205086fd 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -225,6 +225,11 @@ public: static ByteSize cell_offset(int index) { return byte_offset_of(DataLayout, _cells) + in_ByteSize(index * cell_size); } +#ifdef CC_INTERP + static int cell_offset_in_bytes(int index) { + return (int)offset_of(DataLayout, _cells[index]); + } +#endif // CC_INTERP // Return a value which, when or-ed as a byte into _flags, sets the flag. static int flag_number_to_byte_constant(int flag_number) { assert(0 <= flag_number && flag_number < flag_limit, "oob"); @@ -356,6 +361,41 @@ protected: _data = data; } +#ifdef CC_INTERP + // Static low level accessors for DataLayout with ProfileData's semantics. + + static int cell_offset_in_bytes(int index) { + return DataLayout::cell_offset_in_bytes(index); + } + + static void increment_uint_at_no_overflow(DataLayout* layout, int index, + int inc = DataLayout::counter_increment) { + uint count = ((uint)layout->cell_at(index)) + inc; + if (count == 0) return; + layout->set_cell_at(index, (intptr_t) count); + } + + static int int_at(DataLayout* layout, int index) { + return (int)layout->cell_at(index); + } + + static int uint_at(DataLayout* layout, int index) { + return (uint)layout->cell_at(index); + } + + static oop oop_at(DataLayout* layout, int index) { + return (oop)layout->cell_at(index); + } + + static void set_intptr_at(DataLayout* layout, int index, intptr_t value) { + layout->set_cell_at(index, (intptr_t) value); + } + + static void set_flag_at(DataLayout* layout, int flag_number) { + layout->set_flag_at(flag_number); + } +#endif // CC_INTERP + public: // Constructor for invalid ProfileData. ProfileData(); @@ -495,6 +535,20 @@ public: return cell_offset(bit_cell_count); } +#ifdef CC_INTERP + static int bit_data_size_in_bytes() { + return cell_offset_in_bytes(bit_cell_count); + } + + static void set_null_seen(DataLayout* layout) { + set_flag_at(layout, null_seen_flag); + } + + static DataLayout* advance(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)BitData::bit_data_size_in_bytes()); + } +#endif // CC_INTERP + #ifndef PRODUCT void print_data_on(outputStream* st); #endif @@ -539,6 +593,25 @@ public: set_uint_at(count_off, count); } +#ifdef CC_INTERP + static int counter_data_size_in_bytes() { + return cell_offset_in_bytes(counter_cell_count); + } + + static void increment_count_no_overflow(DataLayout* layout) { + increment_uint_at_no_overflow(layout, count_off); + } + + // Support counter decrementation at checkcast / subtype check failed. + static void decrement_count(DataLayout* layout) { + increment_uint_at_no_overflow(layout, count_off, -1); + } + + static DataLayout* advance(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)CounterData::counter_data_size_in_bytes()); + } +#endif // CC_INTERP + #ifndef PRODUCT void print_data_on(outputStream* st); #endif @@ -609,6 +682,20 @@ public: return cell_offset(displacement_off_set); } +#ifdef CC_INTERP + static void increment_taken_count_no_overflow(DataLayout* layout) { + increment_uint_at_no_overflow(layout, taken_off_set); + } + + static DataLayout* advance_taken(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)int_at(layout, displacement_off_set)); + } + + static uint taken_count(DataLayout* layout) { + return (uint) uint_at(layout, taken_off_set); + } +#endif // CC_INTERP + // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -718,6 +805,43 @@ public: // GC support virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure); +#ifdef CC_INTERP + static int receiver_type_data_size_in_bytes() { + return cell_offset_in_bytes(static_cell_count()); + } + + static Klass *receiver_unchecked(DataLayout* layout, uint row) { + oop recv = oop_at(layout, receiver_cell_index(row)); + return (Klass *)recv; + } + + static void increment_receiver_count_no_overflow(DataLayout* layout, Klass *rcvr) { + const int num_rows = row_limit(); + // Receiver already exists? + for (int row = 0; row < num_rows; row++) { + if (receiver_unchecked(layout, row) == rcvr) { + increment_uint_at_no_overflow(layout, receiver_count_cell_index(row)); + return; + } + } + // New receiver, find a free slot. + for (int row = 0; row < num_rows; row++) { + if (receiver_unchecked(layout, row) == NULL) { + set_intptr_at(layout, receiver_cell_index(row), (intptr_t)rcvr); + increment_uint_at_no_overflow(layout, receiver_count_cell_index(row)); + return; + } + } + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + increment_count_no_overflow(layout); + } + + static DataLayout* advance(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)ReceiverTypeData::receiver_type_data_size_in_bytes()); + } +#endif // CC_INTERP + #ifndef PRODUCT void print_receiver_data_on(outputStream* st); void print_data_on(outputStream* st); @@ -751,6 +875,16 @@ public: return cell_offset(static_cell_count()); } +#ifdef CC_INTERP + static int virtual_call_data_size_in_bytes() { + return cell_offset_in_bytes(static_cell_count()); + } + + static DataLayout* advance(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)VirtualCallData::virtual_call_data_size_in_bytes()); + } +#endif // CC_INTERP + #ifndef PRODUCT void print_data_on(outputStream* st); #endif @@ -847,6 +981,10 @@ public: return cell_offset(bci_displacement_cell_index(row)); } +#ifdef CC_INTERP + static DataLayout* advance(MethodData *md, int bci); +#endif // CC_INTERP + // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -911,6 +1049,20 @@ public: return cell_offset(branch_cell_count); } +#ifdef CC_INTERP + static int branch_data_size_in_bytes() { + return cell_offset_in_bytes(branch_cell_count); + } + + static void increment_not_taken_count_no_overflow(DataLayout* layout) { + increment_uint_at_no_overflow(layout, not_taken_off_set); + } + + static DataLayout* advance_not_taken(DataLayout* layout) { + return (DataLayout*) (((address)layout) + (ssize_t)BranchData::branch_data_size_in_bytes()); + } +#endif // CC_INTERP + // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -950,6 +1102,20 @@ protected: set_int_at(aindex, value); } +#ifdef CC_INTERP + // Static low level accessors for DataLayout with ArrayData's semantics. + + static void increment_array_uint_at_no_overflow(DataLayout* layout, int index) { + int aindex = index + array_start_off_set; + increment_uint_at_no_overflow(layout, aindex); + } + + static int array_int_at(DataLayout* layout, int index) { + int aindex = index + array_start_off_set; + return int_at(layout, aindex); + } +#endif // CC_INTERP + // Code generation support for subclasses. static ByteSize array_element_offset(int index) { return cell_offset(array_start_off_set + index); @@ -1068,6 +1234,28 @@ public: return in_ByteSize(relative_displacement_off_set) * cell_size; } +#ifdef CC_INTERP + static void increment_count_no_overflow(DataLayout* layout, int index) { + if (index == -1) { + increment_array_uint_at_no_overflow(layout, default_count_off_set); + } else { + increment_array_uint_at_no_overflow(layout, case_array_start + + index * per_case_cell_count + + relative_count_off_set); + } + } + + static DataLayout* advance(DataLayout* layout, int index) { + if (index == -1) { + return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, default_disaplacement_off_set)); + } else { + return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, case_array_start + + index * per_case_cell_count + + relative_displacement_off_set)); + } + } +#endif // CC_INTERP + // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); @@ -1146,8 +1334,11 @@ public: // adjusted in the event of a change in control flow. // +CC_INTERP_ONLY(class BytecodeInterpreter;) + class MethodData : public Metadata { friend class VMStructs; + CC_INTERP_ONLY(friend class BytecodeInterpreter;) private: friend class ProfileData; diff --git a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp index cd18199aa69..d2dab57a374 100644 --- a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp +++ b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp @@ -117,10 +117,10 @@ jvmtiCapabilities JvmtiManageCapabilities::init_onload_capabilities() { jvmtiCapabilities jc; memset(&jc, 0, sizeof(jc)); -#ifndef CC_INTERP +#ifndef ZERO jc.can_pop_frame = 1; jc.can_force_early_return = 1; -#endif // !CC_INTERP +#endif // !ZERO jc.can_get_source_debug_extension = 1; jc.can_access_local_variables = 1; jc.can_maintain_original_method_order = 1; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ce6317655c6..9ac06335801 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3592,8 +3592,8 @@ jint Arguments::parse(const JavaVMInitArgs* args) { UseBiasedLocking = false; } -#ifdef CC_INTERP - // Clear flags not supported by the C++ interpreter +#ifdef ZERO + // Clear flags not supported on zero. FLAG_SET_DEFAULT(ProfileInterpreter, false); FLAG_SET_DEFAULT(UseBiasedLocking, false); LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false)); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 626ec35cca6..847f9519380 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2727,6 +2727,11 @@ class CommandLineFlags { product_pd(bool, ProfileInterpreter, \ "Profile at the bytecode level during interpretation") \ \ + develop(bool, TraceProfileInterpreter, false, \ + "Trace profiling at the bytecode level during interpretation. " \ + "This outputs the profiling information collected to improve " \ + "jit compilation.") \ + \ develop_pd(bool, ProfileTraps, \ "Profile deoptimization traps at the bytecode level") \ \ From b2c4b12a12c3506881af1ccdfdf70084bea38342 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 16 Oct 2013 10:52:41 +0200 Subject: [PATCH 025/265] 8026487: PPC64: Implement 'os::fork_and_exec' on AIX Reviewed-by: kvn, twisti --- hotspot/src/os/aix/vm/os_aix.cpp | 60 +++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 159ceb4ad1a..049f32242c0 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -227,8 +227,12 @@ julong os::available_memory() { } julong os::Aix::available_memory() { - Unimplemented(); - return 0; + os::Aix::meminfo_t mi; + if (os::Aix::get_meminfo(&mi)) { + return mi.real_free; + } else { + return 0xFFFFFFFFFFFFFFFFLL; + } } julong os::physical_memory() { @@ -5060,8 +5064,56 @@ extern char** environ; // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. int os::fork_and_exec(char* cmd) { - Unimplemented(); - return 0; + char * argv[4] = {"sh", "-c", cmd, NULL}; + + pid_t pid = fork(); + + if (pid < 0) { + // fork failed + return -1; + + } else if (pid == 0) { + // child process + + // try to be consistent with system(), which uses "/usr/bin/sh" on AIX + execve("/usr/bin/sh", argv, environ); + + // execve failed + _exit(-1); + + } else { + // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't + // care about the actual exit code, for now. + + int status; + + // Wait for the child process to exit. This returns immediately if + // the child has already exited. */ + while (waitpid(pid, &status, 0) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (WIFEXITED(status)) { + // The child exited normally; get its exit code. + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + // The child exited because of a signal + // The best value to return is 0x80 + signal number, + // because that is what all Unix shells do, and because + // it allows callers to distinguish between process exit and + // process death by signal. + return 0x80 + WTERMSIG(status); + } else { + // Unknown exit code; pass it through + return status; + } + } + // Remove warning. + return -1; } // is_headless_jre() From 112120d3f9878228d05d4f37ecee042d5115d328 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Nov 2013 11:40:38 +0100 Subject: [PATCH 026/265] 8027964: Adapt PPC to 6843347: Boundary values in some public GC options cause crashes Reviewed-by: dholmes --- hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index dfbe511ea03..6884e960485 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -55,7 +55,7 @@ define_pd_global(bool, RewriteFrequentPairs, true); define_pd_global(bool, UseMembar, false); // GC Ergo Flags -define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // Default max size of CMS young gen, per GC worker thread. +define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // Default max size of CMS young gen, per GC worker thread. // Platform dependent flag handling: flags only defined on this platform. From 570b20f0f1178b6321a9f790ce0ace68a18dc22c Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Nov 2013 11:42:26 +0100 Subject: [PATCH 027/265] 8027965: Adapt PPC to 8015107: NPG: Use consistent naming for metaspace concepts Reviewed-by: dholmes --- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index c72ebbb8b8a..a8d108a4b63 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -2391,7 +2391,7 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src) { } void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { encode_klass_not_null(ck, klass); stw(ck, oopDesc::klass_offset_in_bytes(), dst_oop); } else { @@ -2412,7 +2412,7 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src) { } void MacroAssembler::load_klass(Register dst, Register src) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { lwz(dst, oopDesc::klass_offset_in_bytes(), src); // Attention: no null check here! decode_klass_not_null(dst, dst); From faa041f68f83ce986539796f598f9c28802872c6 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Nov 2013 11:44:53 +0100 Subject: [PATCH 028/265] 8027966: Adapt PPC to 8023657: New type profiling points: arguments to call Reviewed-by: dholmes --- hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index 6884e960485..2dd4b1df167 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -57,6 +57,7 @@ define_pd_global(bool, UseMembar, false); // GC Ergo Flags define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // Default max size of CMS young gen, per GC worker thread. +define_pd_global(uintx, TypeProfileLevel, 0); // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ From 7b010e1c8cbeb7f183e3dcf7a5db75a8f101e383 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Nov 2013 11:51:53 +0100 Subject: [PATCH 029/265] 8027969: Adapt PPC to 8026328: Setting a breakpoint on invokedynamic crashes the JVM Reviewed-by: dholmes, coleenp, sspitsyn --- hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp index c21e55902f3..aaadf69fc93 100644 --- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp @@ -317,7 +317,7 @@ address CppInterpreterGenerator::generate_stack_to_native_abi_converter(BasicTyp return entry; } -address CppInterpreter::return_entry(TosState state, int length) { +address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { assert(interpreter_return_address != NULL, "Not initialized"); return interpreter_return_address; } From d8b9e9f68122b8af31a4e6b961b10fdb10d711c2 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Nov 2013 11:47:11 +0100 Subject: [PATCH 030/265] 8027968: Adapt PPC to 8024927: Nashorn performance regression with CompressedOops Reviewed-by: coleenp, kvn --- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 27 +++++++++++++------ hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp | 1 + hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 5 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index a8d108a4b63..eb716b5b84e 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -2382,10 +2382,12 @@ void MacroAssembler::get_vm_result_2(Register metadata_result) { void MacroAssembler::encode_klass_not_null(Register dst, Register src) { if (src == noreg) src = dst; - assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); - load_const(R0, Universe::narrow_klass_base()); - sub(dst, src, R0); - if (Universe::narrow_klass_shift() != 0) { + if (Universe::narrow_klass_base() != 0) { + load_const(R0, Universe::narrow_klass_base()); + sub(dst, src, R0); + } + if (Universe::narrow_klass_shift() != 0 || + Universe::narrow_klass_base() == 0 && src != dst) { // Move required. srdi(dst, src, Universe::narrow_klass_shift()); } } @@ -2399,16 +2401,25 @@ void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) } } +int MacroAssembler::instr_size_for_decode_klass_not_null() { + if (!UseCompressedClassPointers) return 0; + int num_instrs = 1; // shift or move + if (Universe::narrow_klass_base() != 0) num_instrs = 7; // shift + load const + add + return num_instrs * BytesPerInstWord; +} + void MacroAssembler::decode_klass_not_null(Register dst, Register src) { if (src == noreg) src = dst; Register shifted_src = src; - assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); - if (Universe::narrow_klass_shift() != 0) { + if (Universe::narrow_klass_shift() != 0 || + Universe::narrow_klass_base() == 0 && src != dst) { // Move required. shifted_src = dst; sldi(shifted_src, src, Universe::narrow_klass_shift()); } - load_const(R0, Universe::narrow_klass_base()); - add(dst, shifted_src, R0); + if (Universe::narrow_klass_base() != 0) { + load_const(R0, Universe::narrow_klass_base()); + add(dst, shifted_src, R0); + } } void MacroAssembler::load_klass(Register dst, Register src) { diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp index 35d51499133..7d0a94312d3 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -551,6 +551,7 @@ class MacroAssembler: public Assembler { void load_klass(Register dst, Register src); void load_klass_with_trap_null_check(Register dst, Register src); void store_klass(Register dst_oop, Register klass, Register tmp = R0); + static int instr_size_for_decode_klass_not_null(); void decode_klass_not_null(Register dst, Register src = noreg); void encode_klass_not_null(Register dst, Register src = noreg); diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp index 1b2af584e12..5323e4ae59e 100644 --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -255,10 +255,11 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) { return 1000; } else { + int decode_klass_size = MacroAssembler::instr_size_for_decode_klass_not_null(); if (is_vtable_stub) { - return 20 + 16 + 8; // Plain + (cOops & Traps) + safety + return 20 + decode_klass_size + 8 + 8; // Plain + cOops + Traps + safety } else { - return 16 + 96; + return 96 + decode_klass_size + 12 + 8; // Plain + cOops + Traps + safety } } } From 12b298218de3e5b83a87986da1b94c3824f7f8b5 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 14 Nov 2013 19:24:59 -0800 Subject: [PATCH 031/265] 8003854: PPC64 (part 115): Introduce PostallocExpand that expands nodes after register allocation Added ability in C2 to expand mach nodes to several mach nodes after register allocation Reviewed-by: kvn --- hotspot/src/cpu/sparc/vm/sparc.ad | 8 + hotspot/src/cpu/x86/vm/x86_32.ad | 8 + hotspot/src/cpu/x86/vm/x86_64.ad | 8 + hotspot/src/share/vm/adlc/adlparse.cpp | 201 ++++++++++++++++++-- hotspot/src/share/vm/adlc/adlparse.hpp | 4 +- hotspot/src/share/vm/adlc/archDesc.hpp | 2 + hotspot/src/share/vm/adlc/formssel.cpp | 89 +++++---- hotspot/src/share/vm/adlc/formssel.hpp | 47 ++--- hotspot/src/share/vm/adlc/output_c.cpp | 122 +++++++++++- hotspot/src/share/vm/adlc/output_h.cpp | 7 +- hotspot/src/share/vm/opto/block.cpp | 228 ++++++++++++++++++++++- hotspot/src/share/vm/opto/block.hpp | 7 +- hotspot/src/share/vm/opto/c2_globals.hpp | 3 + hotspot/src/share/vm/opto/compile.cpp | 6 + hotspot/src/share/vm/opto/machnode.cpp | 4 + hotspot/src/share/vm/opto/machnode.hpp | 19 +- hotspot/src/share/vm/opto/matcher.hpp | 4 + hotspot/src/share/vm/opto/node.hpp | 8 +- hotspot/src/share/vm/opto/phase.cpp | 5 + hotspot/src/share/vm/opto/phase.hpp | 1 + 20 files changed, 689 insertions(+), 92 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index b83b657bc35..70275adcc3d 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1034,6 +1034,11 @@ int Compile::ConstantTable::calculate_table_base_offset() const { } } +bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } +void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { + ShouldNotReachHere(); +} + void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { Compile* C = ra_->C; Compile::ConstantTable& constant_table = C->constant_table(); @@ -1884,6 +1889,9 @@ const int Matcher::float_cmove_cost() { return (VM_Version::is_T4() || VM_Version::is_sparc64()) ? ConditionalMoveLimit : 0; } +// Does the CPU require late expand (see block.cpp for description of late expand)? +const bool Matcher::require_postalloc_expand = false; + // Should the Matcher clone shifts on addressing modes, expecting them to // be subsumed into complex addressing expressions or compute them into // registers? True for Intel but false for most RISCs diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 9ed3bfb23b0..00a9861df89 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -487,6 +487,11 @@ int Compile::ConstantTable::calculate_table_base_offset() const { return 0; // absolute addressing, no offset } +bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } +void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { + ShouldNotReachHere(); +} + void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // Empty encoding } @@ -1389,6 +1394,9 @@ const int Matcher::long_cmove_cost() { return 1; } // No CMOVF/CMOVD with SSE/SSE2 const int Matcher::float_cmove_cost() { return (UseSSE>=1) ? ConditionalMoveLimit : 0; } +// Does the CPU require late expand (see block.cpp for description of late expand)? +const bool Matcher::require_postalloc_expand = false; + // Should the Matcher clone shifts on addressing modes, expecting them to // be subsumed into complex addressing expressions or compute them into // registers? True for Intel but false for most RISCs diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 926881a6c28..b94f5a5422c 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -688,6 +688,11 @@ int Compile::ConstantTable::calculate_table_base_offset() const { return 0; // absolute addressing, no offset } +bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } +void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { + ShouldNotReachHere(); +} + void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // Empty encoding } @@ -1542,6 +1547,9 @@ const int Matcher::long_cmove_cost() { return 0; } // No CMOVF/CMOVD with SSE2 const int Matcher::float_cmove_cost() { return ConditionalMoveLimit; } +// Does the CPU require late expand (see block.cpp for description of late expand)? +const bool Matcher::require_postalloc_expand = false; + // Should the Matcher clone shifts on addressing modes, expecting them // to be subsumed into complex addressing expressions or compute them // into registers? True for Intel but false for most RISCs diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 8704c68da69..175bd04cfa2 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -219,19 +219,21 @@ void ADLParser::instr_parse(void) { else if (!strcmp(ident, "encode")) { parse_err(SYNERR, "Instructions specify ins_encode, not encode\n"); } - else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr); - else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); - else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); - else if (!strcmp(ident, "effect")) effect_parse(instr); - else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); - else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); + else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr); + // Parse late expand keyword. + else if (!strcmp(ident, "postalloc_expand")) postalloc_expand_parse(*instr); + else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); + else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); + else if (!strcmp(ident, "effect")) effect_parse(instr); + else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); + else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); else if (!strcmp(ident, "constraint")) { parse_err(SYNERR, "Instructions do not specify a constraint\n"); } else if (!strcmp(ident, "construct")) { parse_err(SYNERR, "Instructions do not specify a construct\n"); } - else if (!strcmp(ident, "format")) instr->_format = format_parse(); + else if (!strcmp(ident, "format")) instr->_format = format_parse(); else if (!strcmp(ident, "interface")) { parse_err(SYNERR, "Instructions do not specify an interface\n"); } @@ -240,13 +242,14 @@ void ADLParser::instr_parse(void) { // Check identifier to see if it is the name of an attribute const Form *form = _globalNames[ident]; AttributeForm *attr = form ? form->is_attribute() : NULL; - if( attr && (attr->_atype == INS_ATTR) ) { + if (attr && (attr->_atype == INS_ATTR)) { // Insert the new attribute into the linked list. Attribute *temp = attr_parse(ident); temp->_next = instr->_attribs; instr->_attribs = temp; } else { - parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident); + parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of" + " an instruction attribute at %s\n", ident); } } skipws(); @@ -258,13 +261,17 @@ void ADLParser::instr_parse(void) { } // Check for "Set" form of chain rule adjust_set_rule(instr); - if (_AD._pipeline ) { - if( instr->expands() ) { - if( instr->_ins_pipe ) - parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\"; ins_pipe will be unused\n", instr->_ident); + if (_AD._pipeline) { + // No pipe required for late expand. + if (instr->expands() || instr->postalloc_expands()) { + if (instr->_ins_pipe) { + parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\";" + " ins_pipe will be unused\n", instr->_ident); + } } else { - if( !instr->_ins_pipe ) + if (!instr->_ins_pipe) { parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident); + } } } // Add instruction to tail of instruction list @@ -2779,11 +2786,13 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) { encoding->add_parameter(opForm->_ident, param); } - // Define a MacroAssembler instance for use by the encoding. The - // name is chosen to match the __ idiom used for assembly in other - // parts of hotspot and assumes the existence of the standard - // #define __ _masm. - encoding->add_code(" MacroAssembler _masm(&cbuf);\n"); + if (!inst._is_postalloc_expand) { + // Define a MacroAssembler instance for use by the encoding. The + // name is chosen to match the __ idiom used for assembly in other + // parts of hotspot and assumes the existence of the standard + // #define __ _masm. + encoding->add_code(" MacroAssembler _masm(&cbuf);\n"); + } // Parse the following %{ }% block ins_encode_parse_block_impl(inst, encoding, ec_name); @@ -2857,7 +2866,8 @@ void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encodi inst.set_is_mach_constant(true); if (_curchar == '(') { - parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name); + parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument " + "(only constantaddress and constantoffset)", ec_name); return; } } @@ -3050,6 +3060,157 @@ void ADLParser::ins_encode_parse(InstructForm& inst) { inst._insencode = encrule; } +//------------------------------postalloc_expand_parse--------------------------- +// Encode rules have the form +// postalloc_expand( encode_class_name(parameter_list) ); +// +// The "encode_class_name" must be defined in the encode section. +// The parameter list contains $names that are locals. +// +// This is just a copy of ins_encode_parse without the loop. +void ADLParser::postalloc_expand_parse(InstructForm& inst) { + inst._is_postalloc_expand = true; + + // Parse encode class name. + skipws(); // Skip whitespace. + if (_curchar != '(') { + // Check for postalloc_expand %{ form + if ((_curchar == '%') && (*(_ptr+1) == '{')) { + next_char(); // Skip '%' + next_char(); // Skip '{' + + // Parse the block form of postalloc_expand + ins_encode_parse_block(inst); + return; + } + + parse_err(SYNERR, "missing '(' in postalloc_expand definition\n"); + return; + } + next_char(); // Move past '('. + skipws(); + + InsEncode *encrule = new InsEncode(); // Encode class for instruction. + encrule->_linenum = linenum(); + char *ec_name = NULL; // String representation of encode rule. + // identifier is optional. + if (_curchar != ')') { + ec_name = get_ident(); + if (ec_name == NULL) { + parse_err(SYNERR, "Invalid postalloc_expand class name after 'postalloc_expand('.\n"); + return; + } + // Check that encoding is defined in the encode section. + EncClass *encode_class = _AD._encode->encClass(ec_name); + + // Get list for encode method's parameters + NameAndList *params = encrule->add_encode(ec_name); + + // Parse the parameters to this encode method. + skipws(); + if (_curchar == '(') { + next_char(); // Move past '(' for parameters. + + // Parse the encode method's parameters. + while (_curchar != ')') { + char *param = get_ident_or_literal_constant("encoding operand"); + if (param != NULL) { + // Found a parameter: + + // First check for constant table support. + + // Check if this instruct is a MachConstantNode. + if (strcmp(param, "constanttablebase") == 0) { + // This instruct is a MachConstantNode. + inst.set_is_mach_constant(true); + + if (_curchar == '(') { + parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument " + "(only constantaddress and constantoffset)", ec_name); + return; + } + } + else if ((strcmp(param, "constantaddress") == 0) || + (strcmp(param, "constantoffset") == 0)) { + // This instruct is a MachConstantNode. + inst.set_is_mach_constant(true); + + // If the constant keyword has an argument, parse it. + if (_curchar == '(') constant_parse(inst); + } + + // Else check it is a local name, add it to the list, then check for more. + // New: allow hex constants as parameters to an encode method. + // New: allow parenthesized expressions as parameters. + // New: allow "primary", "secondary", "tertiary" as parameters. + // New: allow user-defined register name as parameter. + else if ((inst._localNames[param] == NULL) && + !ADLParser::is_literal_constant(param) && + (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && + ((_AD._register == NULL) || (_AD._register->getRegDef(param) == NULL))) { + parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); + return; + } + params->add_entry(param); + + skipws(); + if (_curchar == ',') { + // More parameters to come. + next_char(); // Move past ',' between parameters. + skipws(); // Skip to next parameter. + } else if (_curchar == ')') { + // Done with parameter list + } else { + // Only ',' or ')' are valid after a parameter name. + parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", ec_name); + return; + } + + } else { + skipws(); + // Did not find a parameter. + if (_curchar == ',') { + parse_err(SYNERR, "Expected encode parameter before ',' in postalloc_expand %s.\n", ec_name); + return; + } + if (_curchar != ')') { + parse_err(SYNERR, "Expected ')' after postalloc_expand parameters.\n"); + return; + } + } + } // WHILE loop collecting parameters. + next_char(); // Move past ')' at end of parameters. + } // Done with parameter list for encoding. + + // Check for ',' or ')' after encoding. + skipws(); // Move to character after parameters. + if (_curchar != ')') { + // Only a ')' is allowed. + parse_err(SYNERR, "Expected ')' after postalloc_expand %s.\n", ec_name); + return; + } + } // Done parsing postalloc_expand method and their parameters. + if (_curchar != ')') { + parse_err(SYNERR, "Missing ')' at end of postalloc_expand description.\n"); + return; + } + next_char(); // Move past ')'. + skipws(); // Skip leading whitespace. + + if (_curchar != ';') { + parse_err(SYNERR, "Missing ';' at end of postalloc_expand.\n"); + return; + } + next_char(); // Move past ';'. + skipws(); // Be friendly to oper_parse(). + + // Debug Stuff. + if (_AD._adl_debug > 1) fprintf(stderr, "Instruction postalloc_expand: %s\n", ec_name); + + // Set encode class of this instruction. + inst._insencode = encrule; +} + //------------------------------constant_parse--------------------------------- // Parse a constant expression. diff --git a/hotspot/src/share/vm/adlc/adlparse.hpp b/hotspot/src/share/vm/adlc/adlparse.hpp index 8d87ab9688f..3ea00a24922 100644 --- a/hotspot/src/share/vm/adlc/adlparse.hpp +++ b/hotspot/src/share/vm/adlc/adlparse.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,6 +159,8 @@ protected: void ins_encode_parse(InstructForm &inst); void ins_encode_parse_block(InstructForm &inst); void ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name); + // Parse instruction postalloc expand rule. + void postalloc_expand_parse(InstructForm &inst); void constant_parse(InstructForm& inst); void constant_parse_expression(EncClass* encoding, char* ec_name); diff --git a/hotspot/src/share/vm/adlc/archDesc.hpp b/hotspot/src/share/vm/adlc/archDesc.hpp index f6ae35a9e97..94c7a50fd33 100644 --- a/hotspot/src/share/vm/adlc/archDesc.hpp +++ b/hotspot/src/share/vm/adlc/archDesc.hpp @@ -311,6 +311,8 @@ public: void defineEvalConstant(FILE *fp, InstructForm &node); // Generator for Emit methods for instructions void defineEmit (FILE *fp, InstructForm &node); + // Generator for postalloc_expand methods for instructions. + void define_postalloc_expand(FILE *fp, InstructForm &node); // Define a MachOper encode method void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals, diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index cfa9f5b6222..2e1e341c9df 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -36,27 +36,28 @@ InstructForm::InstructForm(const char *id, bool ideal_only) { _ftype = Form::INS; - _matrule = NULL; - _insencode = NULL; - _constant = NULL; - _opcode = NULL; - _size = NULL; - _attribs = NULL; - _predicate = NULL; - _exprule = NULL; - _rewrule = NULL; - _format = NULL; - _peephole = NULL; - _ins_pipe = NULL; - _uniq_idx = NULL; - _num_uniq = 0; - _cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill + _matrule = NULL; + _insencode = NULL; + _constant = NULL; + _is_postalloc_expand = false; + _opcode = NULL; + _size = NULL; + _attribs = NULL; + _predicate = NULL; + _exprule = NULL; + _rewrule = NULL; + _format = NULL; + _peephole = NULL; + _ins_pipe = NULL; + _uniq_idx = NULL; + _num_uniq = 0; + _cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill _cisc_spill_alternate = NULL; // possible cisc replacement - _cisc_reg_mask_name = NULL; - _is_cisc_alternate = false; - _is_short_branch = false; - _short_branch_form = NULL; - _alignment = 1; + _cisc_reg_mask_name = NULL; + _is_cisc_alternate = false; + _is_short_branch = false; + _short_branch_form = NULL; + _alignment = 1; } InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule) @@ -68,27 +69,28 @@ InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule) { _ftype = Form::INS; - _matrule = rule; - _insencode = instr->_insencode; - _constant = instr->_constant; - _opcode = instr->_opcode; - _size = instr->_size; - _attribs = instr->_attribs; - _predicate = instr->_predicate; - _exprule = instr->_exprule; - _rewrule = instr->_rewrule; - _format = instr->_format; - _peephole = instr->_peephole; - _ins_pipe = instr->_ins_pipe; - _uniq_idx = instr->_uniq_idx; - _num_uniq = instr->_num_uniq; - _cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill - _cisc_spill_alternate = NULL; // possible cisc replacement - _cisc_reg_mask_name = NULL; - _is_cisc_alternate = false; - _is_short_branch = false; - _short_branch_form = NULL; - _alignment = 1; + _matrule = rule; + _insencode = instr->_insencode; + _constant = instr->_constant; + _is_postalloc_expand = instr->_is_postalloc_expand; + _opcode = instr->_opcode; + _size = instr->_size; + _attribs = instr->_attribs; + _predicate = instr->_predicate; + _exprule = instr->_exprule; + _rewrule = instr->_rewrule; + _format = instr->_format; + _peephole = instr->_peephole; + _ins_pipe = instr->_ins_pipe; + _uniq_idx = instr->_uniq_idx; + _num_uniq = instr->_num_uniq; + _cisc_spill_operand = Not_cisc_spillable; // Which operand may cisc-spill + _cisc_spill_alternate = NULL; // possible cisc replacement + _cisc_reg_mask_name = NULL; + _is_cisc_alternate = false; + _is_short_branch = false; + _short_branch_form = NULL; + _alignment = 1; // Copy parameters const char *name; instr->_parameters.reset(); @@ -157,6 +159,11 @@ bool InstructForm::expands() const { return ( _exprule != NULL ); } +// This instruction has a late expand rule? +bool InstructForm::postalloc_expands() const { + return _is_postalloc_expand; +} + // This instruction has a peephole rule? Peephole *InstructForm::peepholes() const { return _peephole; diff --git a/hotspot/src/share/vm/adlc/formssel.hpp b/hotspot/src/share/vm/adlc/formssel.hpp index 3bc22b8e269..0fafe44c953 100644 --- a/hotspot/src/share/vm/adlc/formssel.hpp +++ b/hotspot/src/share/vm/adlc/formssel.hpp @@ -88,30 +88,31 @@ private: public: // Public Data - const char *_ident; // Name of this instruction - NameList _parameters; // Locally defined names - FormDict _localNames; // Table of operands & their types - MatchRule *_matrule; // Matching rule for this instruction - Opcode *_opcode; // Encoding of the opcode for instruction - char *_size; // Size of instruction - InsEncode *_insencode; // Encoding class instruction belongs to - InsEncode *_constant; // Encoding class constant value belongs to - Attribute *_attribs; // List of Attribute rules - Predicate *_predicate; // Predicate test for this instruction - FormDict _effects; // Dictionary of effect rules - ExpandRule *_exprule; // Expand rule for this instruction - RewriteRule *_rewrule; // Rewrite rule for this instruction - FormatRule *_format; // Format for assembly generation - Peephole *_peephole; // List of peephole rules for instruction - const char *_ins_pipe; // Instruction Scheduling description class + const char *_ident; // Name of this instruction + NameList _parameters; // Locally defined names + FormDict _localNames; // Table of operands & their types + MatchRule *_matrule; // Matching rule for this instruction + Opcode *_opcode; // Encoding of the opcode for instruction + char *_size; // Size of instruction + InsEncode *_insencode; // Encoding class instruction belongs to + InsEncode *_constant; // Encoding class constant value belongs to + bool _is_postalloc_expand; // Indicates that encoding just does a lateExpand. + Attribute *_attribs; // List of Attribute rules + Predicate *_predicate; // Predicate test for this instruction + FormDict _effects; // Dictionary of effect rules + ExpandRule *_exprule; // Expand rule for this instruction + RewriteRule *_rewrule; // Rewrite rule for this instruction + FormatRule *_format; // Format for assembly generation + Peephole *_peephole; // List of peephole rules for instruction + const char *_ins_pipe; // Instruction Scheduling description class - uint *_uniq_idx; // Indexes of unique operands - uint _uniq_idx_length; // Length of _uniq_idx array - uint _num_uniq; // Number of unique operands - ComponentList _components; // List of Components matches MachNode's - // operand structure + uint *_uniq_idx; // Indexes of unique operands + uint _uniq_idx_length; // Length of _uniq_idx array + uint _num_uniq; // Number of unique operands + ComponentList _components; // List of Components matches MachNode's + // operand structure - bool _has_call; // contain a call and caller save registers should be saved? + bool _has_call; // contain a call and caller save registers should be saved? // Public Methods InstructForm(const char *id, bool ideal_only = false); @@ -133,6 +134,8 @@ public: virtual uint num_defs_or_kills(); // This instruction has an expand rule? virtual bool expands() const ; + // This instruction has a late expand rule? + virtual bool postalloc_expands() const; // Return this instruction's first peephole rule, or NULL virtual Peephole *peepholes() const; // Add a peephole rule to this instruction diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index b8978591355..53a09d9eb98 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -2488,7 +2488,113 @@ void ArchDesc::defineSize(FILE *fp, InstructForm &inst) { fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size); // (3) and (4) - fprintf(fp,"}\n"); + fprintf(fp,"}\n\n"); +} + +// Emit late expand function. +void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { + InsEncode *ins_encode = inst._insencode; + + // Output instruction's postalloc_expand prototype. + fprintf(fp, "void %sNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) {\n", + inst._ident); + + assert((_encode != NULL) && (ins_encode != NULL), "You must define an encode section."); + + // Output each operand's offset into the array of registers. + inst.index_temps(fp, _globalNames); + + // Output variables "unsigned idx_", Node *n_ and "MachOpnd *op_" + // for each parameter specified in the encoding. + ins_encode->reset(); + const char *ec_name = ins_encode->encode_class_iter(); + assert(ec_name != NULL, "late expand must specify an encoding"); + + EncClass *encoding = _encode->encClass(ec_name); + if (encoding == NULL) { + fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name); + abort(); + } + if (ins_encode->current_encoding_num_args() != encoding->num_args()) { + globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", + inst._ident, ins_encode->current_encoding_num_args(), + ec_name, encoding->num_args()); + } + + fprintf(fp, " // Access to ins and operands for late expand.\n"); + const int buflen = 2000; + char idxbuf[buflen]; char *ib = idxbuf; sprintf(ib, ""); + char nbuf [buflen]; char *nb = nbuf; sprintf(nb, ""); + char opbuf [buflen]; char *ob = opbuf; sprintf(ob, ""); + + encoding->_parameter_type.reset(); + encoding->_parameter_name.reset(); + const char *type = encoding->_parameter_type.iter(); + const char *name = encoding->_parameter_name.iter(); + int param_no = 0; + for (; (type != NULL) && (name != NULL); + (type = encoding->_parameter_type.iter()), (name = encoding->_parameter_name.iter())) { + const char* arg_name = ins_encode->rep_var_name(inst, param_no); + int idx = inst.operand_position_format(arg_name); + if (strcmp(arg_name, "constanttablebase") == 0) { + ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", + name, type, arg_name); + nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); + // There is no operand for the constanttablebase. + } else if (inst.is_noninput_operand(idx)) { + globalAD->syntax_err(inst._linenum, + "In %s: you can not pass the non-input %s to a late expand encoding.\n", + inst._ident, arg_name); + } else { + ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", + name, idx, type, arg_name); + nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); + ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); + } + param_no++; + } + assert(ib < &idxbuf[buflen-1] && nb < &nbuf[buflen-1] && ob < &opbuf[buflen-1], "buffer overflow"); + + fprintf(fp, "%s", idxbuf); + fprintf(fp, " Node *n_region = lookup(0);\n"); + fprintf(fp, "%s%s", nbuf, opbuf); + fprintf(fp, " Compile *C = ra_->C;\n"); + + // Output this instruction's encodings. + fprintf(fp, " {"); + const char *ec_code = NULL; + const char *ec_rep_var = NULL; + assert(encoding == _encode->encClass(ec_name), ""); + + DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst); + encoding->_code.reset(); + encoding->_rep_vars.reset(); + // Process list of user-defined strings, + // and occurrences of replacement variables. + // Replacement Vars are pushed into a list and then output. + while ((ec_code = encoding->_code.iter()) != NULL) { + if (! encoding->_code.is_signal(ec_code)) { + // Emit pending code. + pending.emit(); + pending.clear(); + // Emit this code section. + fprintf(fp, "%s", ec_code); + } else { + // A replacement variable or one of its subfields. + // Obtain replacement variable from list. + ec_rep_var = encoding->_rep_vars.iter(); + pending.add_rep_var(ec_rep_var); + } + } + // Emit pending code. + pending.emit(); + pending.clear(); + fprintf(fp, " }\n"); + + fprintf(fp, "}\n\n"); + + ec_name = ins_encode->encode_class_iter(); + assert(ec_name == NULL, "Late expand may only have one encoding."); } // defineEmit ----------------------------------------------------------------- @@ -2841,7 +2947,7 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob } else if ( (strcmp(name,"disp") == 0) ) { fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); } else { - fprintf(fp,"() const { \n"); + fprintf(fp, "() const {\n"); } // Check for hexadecimal value OR replacement variable @@ -2891,6 +2997,8 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob // Hex value fprintf(fp," return %s;\n", encoding); } else { + globalAD->syntax_err(oper._linenum, "In operand %s: Do not support this encode constant: '%s' for %s.", + oper._ident, encoding, name); assert( false, "Do not support octal or decimal encode constants"); } fprintf(fp," }\n"); @@ -3142,7 +3250,15 @@ void ArchDesc::defineClasses(FILE *fp) { // Ensure this is a machine-world instruction if ( instr->ideal_only() ) continue; - if (instr->_insencode) defineEmit (fp, *instr); + if (instr->_insencode) { + if (instr->postalloc_expands()) { + // Don't write this to _CPP_EXPAND_file, as the code generated calls C-code + // from code sections in ad file that is dumped to fp. + define_postalloc_expand(fp, *instr); + } else { + defineEmit(fp, *instr); + } + } if (instr->is_mach_constant()) defineEvalConstant(fp, *instr); if (instr->_size) defineSize (fp, *instr); diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 538d97fb3e2..a4624f12e38 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1633,7 +1633,12 @@ void ArchDesc::declareClasses(FILE *fp) { // Output the opcode function and the encode function here using the // encoding class information in the _insencode slot. if ( instr->_insencode ) { - fprintf(fp," virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;\n"); + if (instr->postalloc_expands()) { + fprintf(fp," virtual bool requires_postalloc_expand() const { return true; }\n"); + fprintf(fp," virtual void postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_);\n"); + } else { + fprintf(fp," virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;\n"); + } } // virtual function for getting the size of an instruction diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index fade19bdb6b..4b7fc6409ce 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -144,6 +144,10 @@ void Block::find_remove( const Node *n ) { remove_node(find_node(n)); } +bool Block::contains(const Node *n) const { + return _nodes.contains(n); +} + // Return empty status of a block. Empty blocks contain only the head, other // ideal nodes, and an optional trailing goto. int Block::is_Empty() const { @@ -699,7 +703,7 @@ void PhaseCFG::remove_empty_blocks() { // Fix up the final control flow for basic blocks. void PhaseCFG::fixup_flow() { // Fixup final control flow for the blocks. Remove jump-to-next - // block. If neither arm of a IF follows the conditional branch, we + // block. If neither arm of an IF follows the conditional branch, we // have to add a second jump after the conditional. We place the // TRUE branch target in succs[0] for both GOTOs and IFs. for (uint i = 0; i < number_of_blocks(); i++) { @@ -844,6 +848,228 @@ void PhaseCFG::fixup_flow() { } +// postalloc_expand: Expand nodes after register allocation. +// +// postalloc_expand has to be called after register allocation, just +// before output (i.e. scheduling). It only gets called if +// Matcher::require_postalloc_expand is true. +// +// Background: +// +// Nodes that are expandend (one compound node requiring several +// assembler instructions to be implemented split into two or more +// non-compound nodes) after register allocation are not as nice as +// the ones expanded before register allocation - they don't +// participate in optimizations as global code motion. But after +// register allocation we can expand nodes that use registers which +// are not spillable or registers that are not allocated, because the +// old compound node is simply replaced (in its location in the basic +// block) by a new subgraph which does not contain compound nodes any +// more. The scheduler called during output can later on process these +// non-compound nodes. +// +// Implementation: +// +// Nodes requiring postalloc expand are specified in the ad file by using +// a postalloc_expand statement instead of ins_encode. A postalloc_expand +// contains a single call to an encoding, as does an ins_encode +// statement. Instead of an emit() function a postalloc_expand() function +// is generated that doesn't emit assembler but creates a new +// subgraph. The code below calls this postalloc_expand function for each +// node with the appropriate attribute. This function returns the new +// nodes generated in an array passed in the call. The old node, +// potential MachTemps before and potential Projs after it then get +// disconnected and replaced by the new nodes. The instruction +// generating the result has to be the last one in the array. In +// general it is assumed that Projs after the node expanded are +// kills. These kills are not required any more after expanding as +// there are now explicitly visible def-use chains and the Projs are +// removed. This does not hold for calls: They do not only have +// kill-Projs but also Projs defining values. Therefore Projs after +// the node expanded are removed for all but for calls. If a node is +// to be reused, it must be added to the nodes list returned, and it +// will be added again. +// +// Implementing the postalloc_expand function for a node in an enc_class +// is rather tedious. It requires knowledge about many node details, as +// the nodes and the subgraph must be hand crafted. To simplify this, +// adlc generates some utility variables into the postalloc_expand function, +// e.g., holding the operands as specified by the postalloc_expand encoding +// specification, e.g.: +// * unsigned idx_ holding the index of the node in the ins +// * Node *n_ holding the node loaded from the ins +// * MachOpnd *op_ holding the corresponding operand +// +// The ordering of operands can not be determined by looking at a +// rule. Especially if a match rule matches several different trees, +// several nodes are generated from one instruct specification with +// different operand orderings. In this case the adlc generated +// variables are the only way to access the ins and operands +// deterministically. +// +// If assigning a register to a node that contains an oop, don't +// forget to call ra_->set_oop() for the node. +void PhaseCFG::postalloc_expand(PhaseRegAlloc* _ra) { + GrowableArray new_nodes(32); // Array with new nodes filled by postalloc_expand function of node. + GrowableArray remove(32); + GrowableArray succs(32); + unsigned int max_idx = C->unique(); // Remember to distinguish new from old nodes. + DEBUG_ONLY(bool foundNode = false); + + // for all blocks + for (uint i = 0; i < number_of_blocks(); i++) { + Block *b = _blocks[i]; + // For all instructions in the current block. + for (uint j = 0; j < b->number_of_nodes(); j++) { + Node *n = b->get_node(j); + if (n->is_Mach() && n->as_Mach()->requires_postalloc_expand()) { +#ifdef ASSERT + if (TracePostallocExpand) { + if (!foundNode) { + foundNode = true; + tty->print("POSTALLOC EXPANDING %d %s\n", C->compile_id(), + C->method() ? C->method()->name()->as_utf8() : C->stub_name()); + } + tty->print(" postalloc expanding "); n->dump(); + if (Verbose) { + tty->print(" with ins:\n"); + for (uint k = 0; k < n->len(); ++k) { + if (n->in(k)) { tty->print(" "); n->in(k)->dump(); } + } + } + } +#endif + new_nodes.clear(); + // Collect nodes that have to be removed from the block later on. + uint req = n->req(); + remove.clear(); + for (uint k = 0; k < req; ++k) { + if (n->in(k) && n->in(k)->is_MachTemp()) { + remove.push(n->in(k)); // MachTemps which are inputs to the old node have to be removed. + n->in(k)->del_req(0); + j--; + } + } + + // Check whether we can allocate enough nodes. We set a fix limit for + // the size of postalloc expands with this. + uint unique_limit = C->unique() + 40; + if (unique_limit >= _ra->node_regs_max_index()) { + Compile::current()->record_failure("out of nodes in postalloc expand"); + return; + } + + // Emit (i.e. generate new nodes). + n->as_Mach()->postalloc_expand(&new_nodes, _ra); + + assert(C->unique() < unique_limit, "You allocated too many nodes in your postalloc expand."); + + // Disconnect the inputs of the old node. + // + // We reuse MachSpillCopy nodes. If we need to expand them, there + // are many, so reusing pays off. If reused, the node already + // has the new ins. n must be the last node on new_nodes list. + if (!n->is_MachSpillCopy()) { + for (int k = req - 1; k >= 0; --k) { + n->del_req(k); + } + } + +#ifdef ASSERT + // Check that all nodes have proper operands. + for (int k = 0; k < new_nodes.length(); ++k) { + if (new_nodes.at(k)->_idx < max_idx || !new_nodes.at(k)->is_Mach()) continue; // old node, Proj ... + MachNode *m = new_nodes.at(k)->as_Mach(); + for (unsigned int l = 0; l < m->num_opnds(); ++l) { + if (MachOper::notAnOper(m->_opnds[l])) { + outputStream *os = tty; + os->print("Node %s ", m->Name()); + os->print("has invalid opnd %d: %p\n", l, m->_opnds[l]); + assert(0, "Invalid operands, see inline trace in hs_err_pid file."); + } + } + } +#endif + + // Collect succs of old node in remove (for projections) and in succs (for + // all other nodes) do _not_ collect projections in remove (but in succs) + // in case the node is a call. We need the projections for calls as they are + // associated with registes (i.e. they are defs). + succs.clear(); + for (DUIterator k = n->outs(); n->has_out(k); k++) { + if (n->out(k)->is_Proj() && !n->is_MachCall() && !n->is_MachBranch()) { + remove.push(n->out(k)); + } else { + succs.push(n->out(k)); + } + } + // Replace old node n as input of its succs by last of the new nodes. + for (int k = 0; k < succs.length(); ++k) { + Node *succ = succs.at(k); + for (uint l = 0; l < succ->req(); ++l) { + if (succ->in(l) == n) { + succ->set_req(l, new_nodes.at(new_nodes.length() - 1)); + } + } + for (uint l = succ->req(); l < succ->len(); ++l) { + if (succ->in(l) == n) { + succ->set_prec(l, new_nodes.at(new_nodes.length() - 1)); + } + } + } + + // Index of old node in block. + uint index = b->find_node(n); + // Insert new nodes into block and map them in nodes->blocks array + // and remember last node in n2. + Node *n2 = NULL; + for (int k = 0; k < new_nodes.length(); ++k) { + n2 = new_nodes.at(k); + b->insert_node(n2, ++index); + map_node_to_block(n2, b); + } + + // Add old node n to remove and remove them all from block. + remove.push(n); + j--; +#ifdef ASSERT + if (TracePostallocExpand && Verbose) { + tty->print(" removing:\n"); + for (int k = 0; k < remove.length(); ++k) { + tty->print(" "); remove.at(k)->dump(); + } + tty->print(" inserting:\n"); + for (int k = 0; k < new_nodes.length(); ++k) { + tty->print(" "); new_nodes.at(k)->dump(); + } + } +#endif + for (int k = 0; k < remove.length(); ++k) { + if (b->contains(remove.at(k))) { + b->find_remove(remove.at(k)); + } else { + assert(remove.at(k)->is_Proj() && (remove.at(k)->in(0)->is_MachBranch()), ""); + } + } + // If anything has been inserted (n2 != NULL), continue after last node inserted. + // This does not always work. Some postalloc expands don't insert any nodes, if they + // do optimizations (e.g., max(x,x)). In this case we decrement j accordingly. + j = n2 ? b->find_node(n2) : j; + } + } + } + +#ifdef ASSERT + if (foundNode) { + tty->print("FINISHED %d %s\n", C->compile_id(), + C->method() ? C->method()->name()->as_utf8() : C->stub_name()); + tty->flush(); + } +#endif +} + + +//------------------------------dump------------------------------------------- #ifndef PRODUCT void PhaseCFG::_dump_cfg( const Node *end, VectorSet &visited ) const { const Node *x = end->is_block_proj(); diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index e1574691849..1d6028bd5ea 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -313,10 +313,12 @@ public: // Add an instruction to an existing block. It must go after the head // instruction and before the end instruction. void add_inst( Node *n ) { insert_node(n, end_idx()); } - // Find node in block + // Find node in block. Fails if node not in block. uint find_node( const Node *n ) const; // Find and remove n from block list void find_remove( const Node *n ); + // Check wether the node is in the block. + bool contains (const Node *n) const; // Return the empty status of a block enum { not_empty, empty_with_goto, completely_empty }; @@ -596,6 +598,9 @@ class PhaseCFG : public Phase { map_node_to_block(n, b); } + // Check all nodes and postalloc_expand them if necessary. + void postalloc_expand(PhaseRegAlloc* _ra); + #ifndef PRODUCT bool trace_opto_pipelining() const { return _trace_opto_pipelining; } diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index b7ec056660c..6d442111a55 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -463,6 +463,9 @@ experimental(bool, AggressiveUnboxing, false, \ "Control optimizations for aggressive boxing elimination") \ \ + develop(bool, TracePostallocExpand, false, "Trace expanding nodes after" \ + " register allocation.") \ + \ product(bool, DoEscapeAnalysis, true, \ "Perform escape analysis") \ \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index d6dda2b276e..21af9218c31 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -2250,6 +2250,12 @@ void Compile::Code_Gen() { peep.do_transform(); } + // Do late expand if CPU requires this. + if (Matcher::require_postalloc_expand) { + NOT_PRODUCT(TracePhase t2c("postalloc_expand", &_t_postalloc_expand, true)); + cfg.postalloc_expand(_regalloc); + } + // Convert Nodes to instruction bits in a buffer { // %%%% workspace merge brought two timers together for one job diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index a9f00f8381c..a1bcda9599f 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -134,6 +134,10 @@ void MachNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { ShouldNotCallThis(); } +//---------------------------postalloc_expand---------------------------------- +// Expand node after register allocation. +void MachNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) {} + //------------------------------size------------------------------------------- // Size of instruction in bytes uint MachNode::size(PhaseRegAlloc *ra_) const { diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 525135d949b..44d45ca8040 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -155,7 +155,15 @@ public: virtual void ext_format(PhaseRegAlloc *,const MachNode *node,int idx, outputStream *st) const=0; virtual void dump_spec(outputStream *st) const; // Print per-operand info -#endif + + // Check whether o is a valid oper. + static bool notAnOper(const MachOper *o) { + if (o == NULL) return true; + if (((intptr_t)o & 1) != 0) return true; + if (*(address*)o == badAddress) return true; // kill by Node::destruct + return false; + } +#endif // !PRODUCT }; //------------------------------MachNode--------------------------------------- @@ -220,6 +228,12 @@ public: // Emit bytes into cbuf virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; + // Expand node after register allocation. + // Node is replaced by several nodes in the postalloc expand phase. + // Corresponding methods are generated for nodes if they specify + // postalloc_expand. See block.cpp for more documentation. + virtual bool requires_postalloc_expand() const { return false; } + virtual void postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_); // Size of instruction in bytes virtual uint size(PhaseRegAlloc *ra_) const; // Helper function that computes size by emitting code @@ -356,6 +370,9 @@ public: virtual uint ideal_reg() const { return Op_RegP; } virtual uint oper_input_base() const { return 1; } + virtual bool requires_postalloc_expand() const; + virtual void postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_); + virtual void emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const; virtual uint size(PhaseRegAlloc* ra_) const; virtual bool pinned() const { return UseRDPCForConstantTableBase; } diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index 1131d09f1d5..521c188a0d2 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -449,6 +449,10 @@ public: // aligned. static const bool misaligned_doubles_ok; + // Does the CPU require postalloc expand (see block.cpp for description of + // postalloc expand)? + static const bool require_postalloc_expand; + // Perform a platform dependent implicit null fixup. This is needed // on windows95 to take care of some unusual register constraints. void pd_implicit_null_fixup(MachNode *load, uint idx); diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index 924db1b37f9..d380a35f0db 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -357,6 +357,8 @@ protected: // Reference to the i'th input Node. Error if out of bounds. Node* in(uint i) const { assert(i < _max, err_msg_res("oob: i=%d, _max=%d", i, _max)); return _in[i]; } + // Reference to the i'th input Node. NULL if out of bounds. + Node* lookup(uint i) const { return ((i < _max) ? _in[i] : NULL); } // Reference to the i'th output Node. Error if out of bounds. // Use this accessor sparingly. We are going trying to use iterators instead. Node* raw_out(uint i) const { assert(i < _outcnt,"oob"); return _out[i]; } @@ -384,6 +386,10 @@ protected: // Set a required input edge, also updates corresponding output edge void add_req( Node *n ); // Append a NEW required input + void add_req( Node *n0, Node *n1 ) { + add_req(n0); add_req(n1); } + void add_req( Node *n0, Node *n1, Node *n2 ) { + add_req(n0); add_req(n1); add_req(n2); } void add_req_batch( Node* n, uint m ); // Append m NEW required inputs (all n). void del_req( uint idx ); // Delete required edge & compact void del_req_ordered( uint idx ); // Delete required edge & compact with preserved order @@ -1350,7 +1356,7 @@ class Node_List : public Node_Array { public: Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {} Node_List(Arena *a) : Node_Array(a), _cnt(0) {} - bool contains(Node* n) { + bool contains(const Node* n) const { for (uint e = 0; e < size(); e++) { if (at(e) == n) return true; } diff --git a/hotspot/src/share/vm/opto/phase.cpp b/hotspot/src/share/vm/opto/phase.cpp index 5359301575d..7880a9475e1 100644 --- a/hotspot/src/share/vm/opto/phase.cpp +++ b/hotspot/src/share/vm/opto/phase.cpp @@ -26,6 +26,7 @@ #include "code/nmethod.hpp" #include "compiler/compileBroker.hpp" #include "opto/compile.hpp" +#include "opto/matcher.hpp" #include "opto/node.hpp" #include "opto/phase.hpp" @@ -55,6 +56,7 @@ elapsedTimer Phase::_t_blockOrdering; elapsedTimer Phase::_t_macroEliminate; elapsedTimer Phase::_t_macroExpand; elapsedTimer Phase::_t_peephole; +elapsedTimer Phase::_t_postalloc_expand; elapsedTimer Phase::_t_codeGeneration; elapsedTimer Phase::_t_registerMethod; elapsedTimer Phase::_t_temporaryTimer1; @@ -144,6 +146,9 @@ void Phase::print_timers() { } tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds()); tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds()); + if (Matcher::require_postalloc_expand) { + tty->print_cr (" postalloc_expand: %3.3f sec", Phase::_t_postalloc_expand.seconds()); + } tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds()); tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds()); tty->print_cr (" -------------- : ----------"); diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp index 582a126db36..d7eb94dc9d3 100644 --- a/hotspot/src/share/vm/opto/phase.hpp +++ b/hotspot/src/share/vm/opto/phase.hpp @@ -91,6 +91,7 @@ protected: static elapsedTimer _t_macroEliminate; static elapsedTimer _t_macroExpand; static elapsedTimer _t_peephole; + static elapsedTimer _t_postalloc_expand; static elapsedTimer _t_codeGeneration; static elapsedTimer _t_registerMethod; static elapsedTimer _t_temporaryTimer1; From 13b13f525944cae92ff88cc8528e847ee571db30 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 15 Nov 2013 11:05:32 -0800 Subject: [PATCH 032/265] 8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering Add a field to C2 LoadNode and StoreNode classes which indicates whether the load/store should do an acquire/release on platforms which support it. Reviewed-by: kvn --- .../src/share/vm/opto/generateOptoStub.cpp | 18 +- hotspot/src/share/vm/opto/graphKit.cpp | 60 +++--- hotspot/src/share/vm/opto/graphKit.hpp | 50 +++-- hotspot/src/share/vm/opto/idealKit.cpp | 14 +- hotspot/src/share/vm/opto/idealKit.hpp | 1 + hotspot/src/share/vm/opto/library_call.cpp | 65 +++---- hotspot/src/share/vm/opto/macro.cpp | 20 +- hotspot/src/share/vm/opto/matcher.cpp | 13 +- hotspot/src/share/vm/opto/memnode.cpp | 75 ++++---- hotspot/src/share/vm/opto/memnode.hpp | 181 +++++++++++------- hotspot/src/share/vm/opto/mulnode.cpp | 13 +- hotspot/src/share/vm/opto/parse1.cpp | 26 +-- hotspot/src/share/vm/opto/parse2.cpp | 14 +- hotspot/src/share/vm/opto/parse3.cpp | 22 ++- hotspot/src/share/vm/opto/parseHelper.cpp | 18 +- hotspot/src/share/vm/opto/stringopts.cpp | 12 +- hotspot/src/share/vm/opto/vectornode.hpp | 4 +- 17 files changed, 351 insertions(+), 255 deletions(-) diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index 52a6ff64259..16c4bd50752 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -104,13 +104,12 @@ void GraphKit::gen_stub(address C_function, // Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); - store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); + store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias, MemNode::unordered); // Set _thread_in_native // The order of stores into TLS is critical! Setting _thread_in_native MUST // be last, because a GC is allowed at any time after setting it and the GC // will require last_Java_pc and last_Java_sp. - Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset())); //----------------------------- // Compute signature for C call. Varies from the Java signature! @@ -225,16 +224,15 @@ void GraphKit::gen_stub(address C_function, //----------------------------- // Clear last_Java_sp - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); + store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias, MemNode::unordered); // Clear last_Java_pc and (optionally)_flags - store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); + store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias, MemNode::unordered); #if defined(SPARC) - store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); + store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias, MemNode::unordered); #endif /* defined(SPARC) */ #if (defined(IA64) && !defined(AIX)) Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); - store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias); + store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias, MemNode::unordered); #endif // For is-fancy-jump, the C-return value is also the branch target @@ -242,16 +240,16 @@ void GraphKit::gen_stub(address C_function, // Runtime call returning oop in TLS? Fetch it out if( pass_tls ) { Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset())); - Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); + Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered); map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result // clear thread-local-storage(tls) - store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias); + store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias, MemNode::unordered); } //----------------------------- // check exception Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset())); - Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); + Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered); Node* exit_memory = reset_memory(); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 8c5e05c3ac7..518108e7223 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -494,7 +494,7 @@ void GraphKit::uncommon_trap_if_should_post_on_exceptions(Deoptimization::DeoptR // first must access the should_post_on_exceptions_flag in this thread's JavaThread Node* jthread = _gvn.transform(new (C) ThreadLocalNode()); Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset())); - Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, false); + Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered); // Test the should_post_on_exceptions_flag vs. 0 Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) ); @@ -596,7 +596,8 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) { Node *adr = basic_plus_adr(ex_node, ex_node, offset); const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); - Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT); + // Conservatively release stores of object references. + Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, MemNode::release); add_exception_state(make_exception_state(ex_node)); return; @@ -1483,16 +1484,16 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) { // factory methods in "int adr_idx" Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, - bool require_atomic_access) { + MemNode::MemOrd mo, bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); + ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); } ld = _gvn.transform(ld); if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { @@ -1504,6 +1505,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, int adr_idx, + MemNode::MemOrd mo, bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); const TypePtr* adr_type = NULL; @@ -1511,9 +1513,9 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); + st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); } else { - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } st = _gvn.transform(st); set_memory(st, adr_idx); @@ -1613,7 +1615,8 @@ Node* GraphKit::store_oop(Node* ctl, Node* val, const TypeOopPtr* val_type, BasicType bt, - bool use_precise) { + bool use_precise, + MemNode::MemOrd mo) { // Transformation of a value which could be NULL pointer (CastPP #NULL) // could be delayed during Parse (for example, in adjust_map_after_if()). // Execute transformation here to avoid barrier generation in such case. @@ -1633,7 +1636,7 @@ Node* GraphKit::store_oop(Node* ctl, NULL /* pre_val */, bt); - Node* store = store_to_memory(control(), adr, val, bt, adr_idx); + Node* store = store_to_memory(control(), adr, val, bt, adr_idx, mo); post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise); return store; } @@ -1644,7 +1647,8 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl, Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, - BasicType bt) { + BasicType bt, + MemNode::MemOrd mo) { Compile::AliasType* at = C->alias_type(adr_type); const TypeOopPtr* val_type = NULL; if (adr_type->isa_instptr()) { @@ -1663,7 +1667,7 @@ Node* GraphKit::store_oop_to_unknown(Node* ctl, if (val_type == NULL) { val_type = TypeInstPtr::BOTTOM; } - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true); + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo); } @@ -1707,7 +1711,7 @@ Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAr const Type* elemtype = arytype->elem(); BasicType elembt = elemtype->array_element_basic_type(); Node* adr = array_element_address(ary, idx, elembt, arytype->size()); - Node* ld = make_load(ctl, adr, elemtype, elembt, arytype); + Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, MemNode::unordered); return ld; } @@ -1942,9 +1946,9 @@ void GraphKit::increment_counter(address counter_addr) { void GraphKit::increment_counter(Node* counter_addr) { int adr_type = Compile::AliasIdxRaw; Node* ctrl = control(); - Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type); + Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); - store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type ); + store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, MemNode::unordered); } @@ -2525,7 +2529,8 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // First load the super-klass's check-offset Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); - Node *chk_off = _gvn.transform( new (C) LoadINode( NULL, memory(p1), p1, _gvn.type(p1)->is_ptr() ) ); + Node *chk_off = _gvn.transform(new (C) LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(), + TypeInt::INT, MemNode::unordered)); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); @@ -3238,7 +3243,7 @@ Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) { } constant_value = Klass::_lh_neutral_value; // put in a known value Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset())); - return make_load(NULL, lhp, TypeInt::INT, T_INT); + return make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered); } // We just put in an allocate/initialize with a big raw-memory effect. @@ -3773,7 +3778,7 @@ void GraphKit::write_barrier_post(Node* oop_store, // Smash zero into card if( !UseConcMarkSweepGC ) { - __ store(__ ctrl(), card_adr, zero, bt, adr_type); + __ store(__ ctrl(), card_adr, zero, bt, adr_type, MemNode::release); } else { // Specialized path for CM store barrier __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); @@ -3870,9 +3875,9 @@ void GraphKit::g1_write_barrier_pre(bool do_load, // Now get the buffer location we will log the previous value into and store it Node *log_addr = __ AddP(no_base, buffer, next_index); - __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw); + __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw, MemNode::unordered); // update the index - __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw); + __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw, MemNode::unordered); } __ else_(); { @@ -3912,8 +3917,9 @@ void GraphKit::g1_mark_card(IdealKit& ideal, Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); Node* log_addr = __ AddP(no_base, buffer, next_index); - __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw); - __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw); + // Order, see storeCM. + __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered); + __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw, MemNode::unordered); } __ else_(); { __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread()); @@ -4043,7 +4049,7 @@ Node* GraphKit::load_String_offset(Node* ctrl, Node* str) { int offset_field_idx = C->get_alias_index(offset_field_type); return make_load(ctrl, basic_plus_adr(str, str, offset_offset), - TypeInt::INT, T_INT, offset_field_idx); + TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered); } else { return intcon(0); } @@ -4058,7 +4064,7 @@ Node* GraphKit::load_String_length(Node* ctrl, Node* str) { int count_field_idx = C->get_alias_index(count_field_type); return make_load(ctrl, basic_plus_adr(str, str, count_offset), - TypeInt::INT, T_INT, count_field_idx); + TypeInt::INT, T_INT, count_field_idx, MemNode::unordered); } else { return load_array_length(load_String_value(ctrl, str)); } @@ -4074,7 +4080,7 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) { ciTypeArrayKlass::make(T_CHAR), true, 0); int value_field_idx = C->get_alias_index(value_field_type); Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), - value_type, T_OBJECT, value_field_idx); + value_type, T_OBJECT, value_field_idx, MemNode::unordered); // String.value field is known to be @Stable. if (UseImplicitStableValues) { load = cast_array_to_stable(load, value_type); @@ -4089,7 +4095,7 @@ void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) { const TypePtr* offset_field_type = string_type->add_offset(offset_offset); int offset_field_idx = C->get_alias_index(offset_field_type); store_to_memory(ctrl, basic_plus_adr(str, offset_offset), - value, T_INT, offset_field_idx); + value, T_INT, offset_field_idx, MemNode::unordered); } void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { @@ -4099,7 +4105,7 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { const TypePtr* value_field_type = string_type->add_offset(value_offset); store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, - value, TypeAryPtr::CHARS, T_OBJECT); + value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered); } void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { @@ -4109,7 +4115,7 @@ void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { const TypePtr* count_field_type = string_type->add_offset(count_offset); int count_field_idx = C->get_alias_index(count_field_type); store_to_memory(ctrl, basic_plus_adr(str, count_offset), - value, T_INT, count_field_idx); + value, T_INT, count_field_idx, MemNode::unordered); } Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index 75e01784e4c..f505167af3c 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -510,36 +510,50 @@ class GraphKit : public Phase { // Create a LoadNode, reading from the parser's memory state. // (Note: require_atomic_access is useful only with T_LONG.) + // + // We choose the unordered semantics by default because we have + // adapted the `do_put_xxx' and `do_get_xxx' procedures for the case + // of volatile fields. Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, - bool require_atomic_access = false) { + MemNode::MemOrd mo, bool require_atomic_access = false) { // This version computes alias_index from bottom_type return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(), - require_atomic_access); + mo, require_atomic_access); } - Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, bool require_atomic_access = false) { + Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, + MemNode::MemOrd mo, bool require_atomic_access = false) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other make_load factory"); return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type), - require_atomic_access); + mo, require_atomic_access); } // This is the base version which is given an alias index. - Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, bool require_atomic_access = false); + Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, + MemNode::MemOrd mo, bool require_atomic_access = false); // Create & transform a StoreNode and store the effect into the // parser's memory state. + // + // We must ensure that stores of object references will be visible + // only after the object's initialization. So the clients of this + // procedure must indicate that the store requires `release' + // semantics, if the stored value is an object reference that might + // point to a new object and may become externally visible. Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt, const TypePtr* adr_type, + MemNode::MemOrd mo, bool require_atomic_access = false) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other store_to_memory factory"); return store_to_memory(ctl, adr, val, bt, C->get_alias_index(adr_type), - require_atomic_access); + mo, require_atomic_access); } // This is the base version which is given alias index // Return the new StoreXNode Node* store_to_memory(Node* ctl, Node* adr, Node* val, BasicType bt, int adr_idx, + MemNode::MemOrd, bool require_atomic_access = false); @@ -557,40 +571,44 @@ class GraphKit : public Phase { Node* store_oop(Node* ctl, Node* obj, // containing obj - Node* adr, // actual adress to store val at + Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, const TypeOopPtr* val_type, BasicType bt, - bool use_precise); + bool use_precise, + MemNode::MemOrd mo); Node* store_oop_to_object(Node* ctl, Node* obj, // containing obj - Node* adr, // actual adress to store val at + Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, const TypeOopPtr* val_type, - BasicType bt) { - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false); + BasicType bt, + MemNode::MemOrd mo) { + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, false, mo); } Node* store_oop_to_array(Node* ctl, Node* obj, // containing obj - Node* adr, // actual adress to store val at + Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, const TypeOopPtr* val_type, - BasicType bt) { - return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true); + BasicType bt, + MemNode::MemOrd mo) { + return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, mo); } // Could be an array or object we don't know at compile time (unsafe ref.) Node* store_oop_to_unknown(Node* ctl, Node* obj, // containing obj - Node* adr, // actual adress to store val at + Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, - BasicType bt); + BasicType bt, + MemNode::MemOrd mo); // For the few case where the barriers need special help void pre_barrier(bool do_load, Node* ctl, diff --git a/hotspot/src/share/vm/opto/idealKit.cpp b/hotspot/src/share/vm/opto/idealKit.cpp index 90eff2bb5d7..eb5310e0062 100644 --- a/hotspot/src/share/vm/opto/idealKit.cpp +++ b/hotspot/src/share/vm/opto/idealKit.cpp @@ -359,25 +359,25 @@ Node* IdealKit::load(Node* ctl, Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); + ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, MemNode::unordered); } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, MemNode::unordered); } return transform(ld); } Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt, - int adr_idx, - bool require_atomic_access) { - assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); + int adr_idx, + MemNode::MemOrd mo, bool require_atomic_access) { + assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory"); const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); + st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); } else { - st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } st = transform(st); set_memory(st, adr_idx); diff --git a/hotspot/src/share/vm/opto/idealKit.hpp b/hotspot/src/share/vm/opto/idealKit.hpp index 16833c0cbfe..3b92484536b 100644 --- a/hotspot/src/share/vm/opto/idealKit.hpp +++ b/hotspot/src/share/vm/opto/idealKit.hpp @@ -226,6 +226,7 @@ class IdealKit: public StackObj { Node* val, BasicType bt, int adr_idx, + MemNode::MemOrd mo, bool require_atomic_access = false); // Store a card mark ordered after store_oop diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index df6c29f5766..14f7015bd03 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1057,7 +1057,7 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { const Type* thread_type = TypeOopPtr::make_from_klass(thread_klass)->cast_to_ptr_type(TypePtr::NotNull); Node* thread = _gvn.transform(new (C) ThreadLocalNode()); Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::threadObj_offset())); - Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT); + Node* threadObj = make_load(NULL, p, thread_type, T_OBJECT, MemNode::unordered); tls_output = thread; return threadObj; } @@ -2640,7 +2640,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); if (!is_store) { - Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile); + Node* p = make_load(control(), adr, value_type, type, adr_type, MemNode::unordered, is_volatile); // load value switch (type) { case T_BOOLEAN: @@ -2684,13 +2684,14 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas break; } + MemNode::MemOrd mo = is_volatile ? MemNode::release : MemNode::unordered; if (type != T_OBJECT ) { - (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); + (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile); } else { // Possibly an oop being stored to Java heap or native memory if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { // oop to Java heap. - (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); } else { // We can't tell at compile time if we are storing in the Java heap or outside // of it. So we need to emit code to conditionally do the proper type of @@ -2702,11 +2703,11 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas __ if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { // Sync IdealKit and graphKit. sync_kit(ideal); - Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type); + Node* st = store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo); // Update IdealKit memory. __ sync_kit(this); } __ else_(); { - __ store(__ ctrl(), adr, val, type, alias_type->index(), is_volatile); + __ store(__ ctrl(), adr, val, type, alias_type->index(), mo, is_volatile); } __ end_if(); // Final sync IdealKit and GraphKit. final_sync(ideal); @@ -2979,12 +2980,12 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); if (kind == LS_xchg) { load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr, - newval_enc, adr_type, value_type->make_narrowoop())); + newval_enc, adr_type, value_type->make_narrowoop())); } else { assert(kind == LS_cmpxchg, "wrong LoadStore operation"); Node *oldval_enc = _gvn.transform(new (C) EncodePNode(oldval, oldval->bottom_type()->make_narrowoop())); load_store = _gvn.transform(new (C) CompareAndSwapNNode(control(), mem, adr, - newval_enc, oldval_enc)); + newval_enc, oldval_enc)); } } else #endif @@ -3090,9 +3091,9 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { const bool require_atomic_access = true; Node* store; if (type == T_OBJECT) // reference stores need a store barrier. - store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); + store = store_oop_to_unknown(control(), base, adr, adr_type, val, type, MemNode::release); else { - store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); + store = store_to_memory(control(), adr, val, type, adr_type, MemNode::release, require_atomic_access); } insert_mem_bar(Op_MemBarCPUOrder); return true; @@ -3152,7 +3153,7 @@ bool LibraryCallKit::inline_unsafe_allocate() { Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset())); // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler // can generate code to load it as unsigned byte. - Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN); + Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered); Node* bits = intcon(InstanceKlass::fully_initialized); test = _gvn.transform(new (C) SubINode(inst, bits)); // The 'test' is non-zero if we need to take a slow path. @@ -3176,14 +3177,14 @@ bool LibraryCallKit::inline_native_classID() { kls = null_check(kls, T_OBJECT); ByteSize offset = TRACE_ID_OFFSET; Node* insp = basic_plus_adr(kls, in_bytes(offset)); - Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG); + Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); Node* bits = longcon(~0x03l); // ignore bit 0 & 1 Node* andl = _gvn.transform(new (C) AndLNode(tvalue, bits)); Node* clsused = longcon(0x01l); // set the class bit Node* orl = _gvn.transform(new (C) OrLNode(tvalue, clsused)); const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); - store_to_memory(control(), insp, orl, T_LONG, adr_type); + store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); set_result(andl); return true; } @@ -3192,15 +3193,15 @@ bool LibraryCallKit::inline_native_threadID() { Node* tls_ptr = NULL; Node* cur_thr = generate_current_thread(tls_ptr); Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); + Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); Node* threadid = NULL; size_t thread_id_size = OSThread::thread_id_size(); if (thread_id_size == (size_t) BytesPerLong) { - threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG)); + threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); } else if (thread_id_size == (size_t) BytesPerInt) { - threadid = make_load(control(), p, TypeInt::INT, T_INT); + threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); } else { ShouldNotReachHere(); } @@ -3275,11 +3276,11 @@ bool LibraryCallKit::inline_native_isInterrupted() { // (b) Interrupt bit on TLS must be false. Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); + Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); // Set the control input on the field _interrupted read to prevent it floating up. - Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); + Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT, MemNode::unordered); Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0))); Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne)); @@ -3347,7 +3348,7 @@ bool LibraryCallKit::inline_native_isInterrupted() { // Given a klass oop, load its java mirror (a java.lang.Class oop). Node* LibraryCallKit::load_mirror_from_klass(Node* klass) { Node* p = basic_plus_adr(klass, in_bytes(Klass::java_mirror_offset())); - return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT); + return make_load(NULL, p, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); } //-----------------------load_klass_from_mirror_common------------------------- @@ -3384,7 +3385,7 @@ Node* LibraryCallKit::generate_access_flags_guard(Node* kls, int modifier_mask, // Branch around if the given klass has the given modifier bit set. // Like generate_guard, adds a new path onto the region. Node* modp = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); - Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT); + Node* mods = make_load(NULL, modp, TypeInt::INT, T_INT, MemNode::unordered); Node* mask = intcon(modifier_mask); Node* bits = intcon(modifier_bits); Node* mbit = _gvn.transform(new (C) AndINode(mods, mask)); @@ -3501,7 +3502,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { case vmIntrinsics::_getModifiers: p = basic_plus_adr(kls, in_bytes(Klass::modifier_flags_offset())); - query_value = make_load(NULL, p, TypeInt::INT, T_INT); + query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); break; case vmIntrinsics::_isInterface: @@ -3559,7 +3560,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { // Be sure to pin the oop load to the guard edge just created: Node* is_array_ctrl = region->in(region->req()-1); Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset())); - Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT); + Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT, MemNode::unordered); phi->add_req(cmo); } query_value = null(); // non-array case is null @@ -3567,7 +3568,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { case vmIntrinsics::_getClassAccessFlags: p = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset())); - query_value = make_load(NULL, p, TypeInt::INT, T_INT); + query_value = make_load(NULL, p, TypeInt::INT, T_INT, MemNode::unordered); break; default: @@ -3933,7 +3934,7 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, vtable_index*vtableEntry::size()) * wordSize + vtableEntry::method_offset_in_bytes(); Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); - Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS); + Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS, MemNode::unordered); // Compare the target method with the expected method (e.g., Object.hashCode). const TypePtr* native_call_addr = TypeMetadataPtr::make(method); @@ -4059,7 +4060,7 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { // Get the header out of the object, use LoadMarkNode when available Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); - Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type()); + Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); // Test the header to see if it is unlocked. Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); @@ -5480,7 +5481,7 @@ LibraryCallKit::generate_clear_array(const TypePtr* adr_type, // Store a zero to the immediately preceding jint: Node* x1 = _gvn.transform(new(C) AddXNode(start, MakeConX(-bump_bit))); Node* p1 = basic_plus_adr(dest, x1); - mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT); + mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered); mem = _gvn.transform(mem); } } @@ -5530,8 +5531,8 @@ LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type, ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { Node* sptr = basic_plus_adr(src, src_off); Node* dptr = basic_plus_adr(dest, dest_off); - Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type); - store_to_memory(control(), dptr, sval, T_INT, adr_type); + Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); + store_to_memory(control(), dptr, sval, T_INT, adr_type, MemNode::unordered); src_off += BytesPerInt; dest_off += BytesPerInt; } else { @@ -5596,7 +5597,7 @@ LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, // super_check_offset, for the desired klass. int sco_offset = in_bytes(Klass::super_check_offset_offset()); Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); - Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr()); + Node* n3 = new(C) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered); Node* check_offset = ConvI2X(_gvn.transform(n3)); Node* check_value = dest_elem_klass; @@ -5737,7 +5738,7 @@ bool LibraryCallKit::inline_updateCRC32() { Node* base = makecon(TypeRawPtr::make(StubRoutines::crc_table_addr())); Node* offset = _gvn.transform(new (C) LShiftINode(result, intcon(0x2))); Node* adr = basic_plus_adr(top(), base, ConvI2X(offset)); - result = make_load(control(), adr, TypeInt::INT, T_INT); + result = make_load(control(), adr, TypeInt::INT, T_INT, MemNode::unordered); crc = _gvn.transform(new (C) URShiftINode(crc, intcon(8))); result = _gvn.transform(new (C) XorINode(crc, result)); @@ -5838,7 +5839,7 @@ bool LibraryCallKit::inline_reference_get() { const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass); Node* no_ctrl = NULL; - Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT); + Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT, MemNode::unordered); // Use the pre-barrier to record the value in the referent field pre_barrier(false /* do_load */, @@ -5885,7 +5886,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass()); // Build the load. - Node* loadedField = make_load(NULL, adr, type, bt, adr_type, is_vol); + Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); return loadedField; } diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 06bf9e608c0..67bae145414 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -1084,7 +1084,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) { Node* adr = basic_plus_adr(base, offset); const TypePtr* adr_type = adr->bottom_type()->is_ptr(); - Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt); + Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt, MemNode::unordered); transform_later(value); return value; } @@ -1092,7 +1092,7 @@ Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) { Node* adr = basic_plus_adr(base, offset); - mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt); + mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt, MemNode::unordered); transform_later(mem); return mem; } @@ -1272,8 +1272,8 @@ void PhaseMacroExpand::expand_allocate_common( // Load(-locked) the heap top. // See note above concerning the control input when using a TLAB Node *old_eden_top = UseTLAB - ? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) - : new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr); + ? new (C) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered) + : new (C) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire); transform_later(old_eden_top); // Add to heap top to get a new heap top @@ -1320,7 +1320,7 @@ void PhaseMacroExpand::expand_allocate_common( if (UseTLAB) { Node* store_eden_top = new (C) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr, - TypeRawPtr::BOTTOM, new_eden_top); + TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered); transform_later(store_eden_top); fast_oop_ctrl = needgc_false; // No contention, so this is the fast path fast_oop_rawmem = store_eden_top; @@ -1700,9 +1700,10 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, _igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset())) ); transform_later(eden_pf_adr); - Node *old_pf_wm = new (C) LoadPNode( needgc_false, + Node *old_pf_wm = new (C) LoadPNode(needgc_false, contended_phi_rawmem, eden_pf_adr, - TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); + TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, + MemNode::unordered); transform_later(old_pf_wm); // check against new_eden_top @@ -1726,9 +1727,10 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, transform_later(new_pf_wmt ); new_pf_wmt->set_req(0, need_pf_true); - Node *store_new_wmt = new (C) StorePNode( need_pf_true, + Node *store_new_wmt = new (C) StorePNode(need_pf_true, contended_phi_rawmem, eden_pf_adr, - TypeRawPtr::BOTTOM, new_pf_wmt ); + TypeRawPtr::BOTTOM, new_pf_wmt, + MemNode::unordered); transform_later(store_new_wmt); // adding prefetches diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 8b38170f6ca..436ade10a97 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -825,16 +825,15 @@ void Matcher::init_spill_mask( Node *ret ) { // Compute generic short-offset Loads #ifdef _LP64 - MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); + MachNode *spillCP = match_tree(new (C) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); #endif - MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp)); - MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp)); - MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp)); - MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp)); - MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); + MachNode *spillI = match_tree(new (C) LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered)); + MachNode *spillL = match_tree(new (C) LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false)); + MachNode *spillF = match_tree(new (C) LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered)); + MachNode *spillD = match_tree(new (C) LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered)); + MachNode *spillP = match_tree(new (C) LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); assert(spillI != NULL && spillL != NULL && spillF != NULL && spillD != NULL && spillP != NULL, ""); - // Get the ADLC notion of the right regmask, for each basic type. #ifdef _LP64 idealreg2regmask[Op_RegN] = &spillCP->out_RegMask(); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 49694b6e92e..db956862482 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -907,7 +907,7 @@ bool LoadNode::is_immutable_value(Node* adr) { //----------------------------LoadNode::make----------------------------------- // Polymorphic factory method: -Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) { +Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) { Compile* C = gvn.C; // sanity check the alias category against the created node type @@ -923,34 +923,34 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type rt->isa_oopptr() || is_immutable_value(adr), "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); - case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); - case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() ); - case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() ); - case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt ); - case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt ); - case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() ); + case T_BOOLEAN: return new (C) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo); + case T_BYTE: return new (C) LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo); + case T_INT: return new (C) LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo); + case T_CHAR: return new (C) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo); + case T_SHORT: return new (C) LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo); + case T_LONG: return new (C) LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo); + case T_FLOAT: return new (C) LoadFNode (ctl, mem, adr, adr_type, rt, mo); + case T_DOUBLE: return new (C) LoadDNode (ctl, mem, adr, adr_type, rt, mo); + case T_ADDRESS: return new (C) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo); case T_OBJECT: #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { - Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop())); + Node* load = gvn.transform(new (C) LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo)); return new (C) DecodeNNode(load, load->bottom_type()->make_ptr()); } else #endif { assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop"); - return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); + return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo); } } ShouldNotReachHere(); return (LoadNode*)NULL; } -LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt) { +LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { bool require_atomic = true; - return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), require_atomic); + return new (C) LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic); } @@ -2032,12 +2032,12 @@ Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* a #ifdef _LP64 if (adr_type->is_ptr_to_narrowklass()) { assert(UseCompressedClassPointers, "no compressed klasses"); - Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass())); + Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass(), MemNode::unordered)); return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr()); } #endif assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop"); - return new (C) LoadKlassNode(ctl, mem, adr, at, tk); + return new (C) LoadKlassNode(ctl, mem, adr, at, tk, MemNode::unordered); } //------------------------------Value------------------------------------------ @@ -2347,45 +2347,46 @@ Node* LoadRangeNode::Identity( PhaseTransform *phase ) { //============================================================================= //---------------------------StoreNode::make----------------------------------- // Polymorphic factory method: -StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) { +StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt, MemOrd mo) { + assert((mo == unordered || mo == release), "unexpected"); Compile* C = gvn.C; - assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw || - ctl != NULL, "raw memory operations should have control edge"); + assert(C->get_alias_index(adr_type) != Compile::AliasIdxRaw || + ctl != NULL, "raw memory operations should have control edge"); switch (bt) { case T_BOOLEAN: - case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val); - case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val); + case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val, mo); + case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: - case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val); - case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val); - case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val); - case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val); + case T_SHORT: return new (C) StoreCNode(ctl, mem, adr, adr_type, val, mo); + case T_LONG: return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo); + case T_FLOAT: return new (C) StoreFNode(ctl, mem, adr, adr_type, val, mo); + case T_DOUBLE: return new (C) StoreDNode(ctl, mem, adr, adr_type, val, mo); case T_METADATA: case T_ADDRESS: case T_OBJECT: #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop())); - return new (C) StoreNNode(ctl, mem, adr, adr_type, val); + return new (C) StoreNNode(ctl, mem, adr, adr_type, val, mo); } else if (adr->bottom_type()->is_ptr_to_narrowklass() || (UseCompressedClassPointers && val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass())); - return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val); + return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val, mo); } #endif { - return new (C) StorePNode(ctl, mem, adr, adr_type, val); + return new (C) StorePNode(ctl, mem, adr, adr_type, val, mo); } } ShouldNotReachHere(); return (StoreNode*)NULL; } -StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val) { +StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { bool require_atomic = true; - return new (C) StoreLNode(ctl, mem, adr, adr_type, val, require_atomic); + return new (C) StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic); } @@ -2778,12 +2779,12 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ Node *zero = phase->makecon(TypeLong::ZERO); Node *off = phase->MakeConX(BytesPerLong); - mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); + mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false); count--; while( count-- ) { mem = phase->transform(mem); adr = phase->transform(new (phase->C) AddPNode(base,adr,off)); - mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero); + mem = new (phase->C) StoreLNode(in(0),mem,adr,atp,zero,MemNode::unordered,false); } return mem; } @@ -2827,7 +2828,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(offset)); adr = phase->transform(adr); const TypePtr* atp = TypeRawPtr::BOTTOM; - mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered); mem = phase->transform(mem); offset += BytesPerInt; } @@ -2888,7 +2889,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, Node* adr = new (C) AddPNode(dest, dest, phase->MakeConX(done_offset)); adr = phase->transform(adr); const TypePtr* atp = TypeRawPtr::BOTTOM; - mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT, MemNode::unordered); mem = phase->transform(mem); done_offset += BytesPerInt; } @@ -3762,14 +3763,14 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size, ++new_long; off[nst] = offset; st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, - phase->longcon(con), T_LONG); + phase->longcon(con), T_LONG, MemNode::unordered); } else { // Omit either if it is a zero. if (con0 != 0) { ++new_int; off[nst] = offset; st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, - phase->intcon(con0), T_INT); + phase->intcon(con0), T_INT, MemNode::unordered); } if (con1 != 0) { ++new_int; @@ -3777,7 +3778,7 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size, adr = make_raw_address(offset, phase); off[nst] = offset; st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, - phase->intcon(con1), T_INT); + phase->intcon(con1), T_INT, MemNode::unordered); } } diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 9a009908453..c0b7073b8bc 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -51,6 +51,10 @@ public: ValueIn, // Value to store OopStore // Preceeding oop store, only in StoreCM }; + typedef enum { unordered = 0, + acquire, // Load has to acquire or be succeeded by MemBarAcquire. + release // Store has to release or be preceded by MemBarRelease. + } MemOrd; protected: MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at ) : Node(c0,c1,c2 ) { @@ -134,20 +138,32 @@ public: //------------------------------LoadNode--------------------------------------- // Load value; requires Memory and Address class LoadNode : public MemNode { +private: + // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish + // loads that can be reordered, and such requiring acquire semantics to + // adhere to the Java specification. The required behaviour is stored in + // this field. + const MemOrd _mo; + protected: - virtual uint cmp( const Node &n ) const; + virtual uint cmp(const Node &n) const; virtual uint size_of() const; // Size is bigger const Type* const _type; // What kind of value is loaded? public: - LoadNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt ) - : MemNode(c,mem,adr,at), _type(rt) { + LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo) + : MemNode(c,mem,adr,at), _type(rt), _mo(mo) { init_class_id(Class_Load); } + inline bool is_unordered() const { return !is_acquire(); } + inline bool is_acquire() const { + assert(_mo == unordered || _mo == acquire, "unexpected"); + return _mo == acquire; + } // Polymorphic factory method: - static Node* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, - const TypePtr* at, const Type *rt, BasicType bt ); + static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, + const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo); virtual uint hash() const; // Check the type @@ -210,8 +226,8 @@ protected: // Load a byte (8bits signed) from memory class LoadBNode : public LoadNode { public: - LoadBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::BYTE ) - : LoadNode(c,mem,adr,at,ti) {} + LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) + : LoadNode(c, mem, adr, at, ti, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -224,8 +240,8 @@ public: // Load a unsigned byte (8bits unsigned) from memory class LoadUBNode : public LoadNode { public: - LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti = TypeInt::UBYTE ) - : LoadNode(c, mem, adr, at, ti) {} + LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo) + : LoadNode(c, mem, adr, at, ti, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); @@ -238,8 +254,8 @@ public: // Load an unsigned short/char (16bits unsigned) from memory class LoadUSNode : public LoadNode { public: - LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) - : LoadNode(c,mem,adr,at,ti) {} + LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) + : LoadNode(c, mem, adr, at, ti, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -252,8 +268,8 @@ public: // Load a short (16bits signed) from memory class LoadSNode : public LoadNode { public: - LoadSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::SHORT ) - : LoadNode(c,mem,adr,at,ti) {} + LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) + : LoadNode(c, mem, adr, at, ti, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -266,8 +282,8 @@ public: // Load an integer from memory class LoadINode : public LoadNode { public: - LoadINode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::INT ) - : LoadNode(c,mem,adr,at,ti) {} + LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) + : LoadNode(c, mem, adr, at, ti, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual int store_Opcode() const { return Op_StoreI; } @@ -278,8 +294,8 @@ public: // Load an array length from the array class LoadRangeNode : public LoadINode { public: - LoadRangeNode( Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS ) - : LoadINode(c,mem,adr,TypeAryPtr::RANGE,ti) {} + LoadRangeNode(Node *c, Node *mem, Node *adr, const TypeInt *ti = TypeInt::POS) + : LoadINode(c, mem, adr, TypeAryPtr::RANGE, ti, MemNode::unordered) {} virtual int Opcode() const; virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); @@ -298,18 +314,16 @@ class LoadLNode : public LoadNode { const bool _require_atomic_access; // is piecewise load forbidden? public: - LoadLNode( Node *c, Node *mem, Node *adr, const TypePtr* at, - const TypeLong *tl = TypeLong::LONG, - bool require_atomic_access = false ) - : LoadNode(c,mem,adr,at,tl) - , _require_atomic_access(require_atomic_access) - {} + LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl, + MemOrd mo, bool require_atomic_access = false) + : LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegL; } virtual int store_Opcode() const { return Op_StoreL; } virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() { return _require_atomic_access; } - static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt); + static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, + const Type* rt, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -322,8 +336,8 @@ public: // Load a long from unaligned memory class LoadL_unalignedNode : public LoadLNode { public: - LoadL_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at ) - : LoadLNode(c,mem,adr,at) {} + LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) + : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {} virtual int Opcode() const; }; @@ -331,8 +345,8 @@ public: // Load a float (64 bits) from memory class LoadFNode : public LoadNode { public: - LoadFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::FLOAT ) - : LoadNode(c,mem,adr,at,t) {} + LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo) + : LoadNode(c, mem, adr, at, t, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegF; } virtual int store_Opcode() const { return Op_StoreF; } @@ -343,8 +357,8 @@ public: // Load a double (64 bits) from memory class LoadDNode : public LoadNode { public: - LoadDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t = Type::DOUBLE ) - : LoadNode(c,mem,adr,at,t) {} + LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo) + : LoadNode(c, mem, adr, at, t, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegD; } virtual int store_Opcode() const { return Op_StoreD; } @@ -355,8 +369,8 @@ public: // Load a double from unaligned memory class LoadD_unalignedNode : public LoadDNode { public: - LoadD_unalignedNode( Node *c, Node *mem, Node *adr, const TypePtr* at ) - : LoadDNode(c,mem,adr,at) {} + LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) + : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {} virtual int Opcode() const; }; @@ -364,8 +378,8 @@ public: // Load a pointer from memory (either object or array) class LoadPNode : public LoadNode { public: - LoadPNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t ) - : LoadNode(c,mem,adr,at,t) {} + LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo) + : LoadNode(c, mem, adr, at, t, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegP; } virtual int store_Opcode() const { return Op_StoreP; } @@ -387,8 +401,8 @@ public: // Load a narrow oop from memory (either object or array) class LoadNNode : public LoadNode { public: - LoadNNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t ) - : LoadNode(c,mem,adr,at,t) {} + LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo) + : LoadNode(c, mem, adr, at, t, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegN; } virtual int store_Opcode() const { return Op_StoreN; } @@ -409,8 +423,8 @@ public: // Load a Klass from an object class LoadKlassNode : public LoadPNode { public: - LoadKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk ) - : LoadPNode(c,mem,adr,at,tk) {} + LoadKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk, MemOrd mo) + : LoadPNode(c, mem, adr, at, tk, mo) {} virtual int Opcode() const; virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); @@ -425,8 +439,8 @@ public: // Load a narrow Klass from an object. class LoadNKlassNode : public LoadNNode { public: - LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk ) - : LoadNNode(c,mem,adr,at,tk) {} + LoadNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk, MemOrd mo) + : LoadNNode(c, mem, adr, at, tk, mo) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegN; } virtual int store_Opcode() const { return Op_StoreNKlass; } @@ -441,6 +455,14 @@ public: //------------------------------StoreNode-------------------------------------- // Store value; requires Store, Address and Value class StoreNode : public MemNode { +private: + // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish + // stores that can be reordered, and such requiring release semantics to + // adhere to the Java specification. The required behaviour is stored in + // this field. + const MemOrd _mo; + // Needed for proper cloning. + virtual uint size_of() const { return sizeof(*this); } protected: virtual uint cmp( const Node &n ) const; virtual bool depends_only_on_test() const { return false; } @@ -449,18 +471,44 @@ protected: Node *Ideal_sign_extended_input(PhaseGVN *phase, int num_bits); public: - StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) - : MemNode(c,mem,adr,at,val) { + // We must ensure that stores of object references will be visible + // only after the object's initialization. So the callers of this + // procedure must indicate that the store requires `release' + // semantics, if the stored value is an object reference that might + // point to a new object and may become externally visible. + StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : MemNode(c, mem, adr, at, val), _mo(mo) { init_class_id(Class_Store); } - StoreNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store ) - : MemNode(c,mem,adr,at,val,oop_store) { + StoreNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, MemOrd mo) + : MemNode(c, mem, adr, at, val, oop_store), _mo(mo) { init_class_id(Class_Store); } - // Polymorphic factory method: - static StoreNode* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, - const TypePtr* at, Node *val, BasicType bt ); + inline bool is_unordered() const { return !is_release(); } + inline bool is_release() const { + assert((_mo == unordered || _mo == release), "unexpected"); + return _mo == release; + } + + // Conservatively release stores of object references in order to + // ensure visibility of object initialization. + static inline MemOrd release_if_reference(const BasicType t) { + const MemOrd mo = (t == T_ARRAY || + t == T_ADDRESS || // Might be the address of an object reference (`boxing'). + t == T_OBJECT) ? release : unordered; + return mo; + } + + // Polymorphic factory method + // + // We must ensure that stores of object references will be visible + // only after the object's initialization. So the callers of this + // procedure must indicate that the store requires `release' + // semantics, if the stored value is an object reference that might + // point to a new object and may become externally visible. + static StoreNode* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, + const TypePtr* at, Node *val, BasicType bt, MemOrd mo); virtual uint hash() const; // Check the type @@ -491,7 +539,8 @@ public: // Store byte to memory class StoreBNode : public StoreNode { public: - StoreBNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual BasicType memory_type() const { return T_BYTE; } @@ -501,7 +550,8 @@ public: // Store char/short to memory class StoreCNode : public StoreNode { public: - StoreCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreCNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual BasicType memory_type() const { return T_CHAR; } @@ -511,7 +561,8 @@ public: // Store int to memory class StoreINode : public StoreNode { public: - StoreINode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreINode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_INT; } }; @@ -528,15 +579,12 @@ class StoreLNode : public StoreNode { const bool _require_atomic_access; // is piecewise store forbidden? public: - StoreLNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, - bool require_atomic_access = false ) - : StoreNode(c,mem,adr,at,val) - , _require_atomic_access(require_atomic_access) - {} + StoreLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo, bool require_atomic_access = false) + : StoreNode(c, mem, adr, at, val, mo), _require_atomic_access(require_atomic_access) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() { return _require_atomic_access; } - static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val); + static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -549,7 +597,8 @@ public: // Store float to memory class StoreFNode : public StoreNode { public: - StoreFNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_FLOAT; } }; @@ -558,7 +607,8 @@ public: // Store double to memory class StoreDNode : public StoreNode { public: - StoreDNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_DOUBLE; } }; @@ -567,7 +617,8 @@ public: // Store pointer to memory class StorePNode : public StoreNode { public: - StorePNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StorePNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_ADDRESS; } }; @@ -576,7 +627,8 @@ public: // Store narrow oop to memory class StoreNNode : public StoreNode { public: - StoreNNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + StoreNNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_NARROWOOP; } }; @@ -585,7 +637,8 @@ public: // Store narrow klass to memory class StoreNKlassNode : public StoreNNode { public: - StoreNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNNode(c,mem,adr,at,val) {} + StoreNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreNNode(c, mem, adr, at, val, mo) {} virtual int Opcode() const; virtual BasicType memory_type() const { return T_NARROWKLASS; } }; @@ -606,7 +659,7 @@ class StoreCMNode : public StoreNode { public: StoreCMNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, Node *oop_store, int oop_alias_idx ) : - StoreNode(c,mem,adr,at,val,oop_store), + StoreNode(c, mem, adr, at, val, oop_store, MemNode::release), _oop_alias_idx(oop_alias_idx) { assert(_oop_alias_idx >= Compile::AliasIdxRaw || _oop_alias_idx == Compile::AliasIdxBot && Compile::current()->AliasLevel() == 0, @@ -626,8 +679,8 @@ public: // On PowerPC and friends it's a real load-locked. class LoadPLockedNode : public LoadPNode { public: - LoadPLockedNode( Node *c, Node *mem, Node *adr ) - : LoadPNode(c,mem,adr,TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) {} + LoadPLockedNode(Node *c, Node *mem, Node *adr, MemOrd mo) + : LoadPNode(c, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, mo) {} virtual int Opcode() const; virtual int store_Opcode() const { return Op_StorePConditional; } virtual bool depends_only_on_test() const { return true; } diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 4047b933fbd..4896e98a7f0 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -485,7 +485,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *ldus = new (phase->C) LoadUSNode(load->in(MemNode::Control), load->in(MemNode::Memory), load->in(MemNode::Address), - load->adr_type()); + load->adr_type(), + TypeInt::CHAR, MemNode::unordered); ldus = phase->transform(ldus); return new (phase->C) AndINode(ldus, phase->intcon(mask & 0xFFFF)); } @@ -496,7 +497,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* ldub = new (phase->C) LoadUBNode(load->in(MemNode::Control), load->in(MemNode::Memory), load->in(MemNode::Address), - load->adr_type()); + load->adr_type(), + TypeInt::UBYTE, MemNode::unordered); ldub = phase->transform(ldub); return new (phase->C) AndINode(ldub, phase->intcon(mask)); } @@ -931,9 +933,10 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { ld->outcnt() == 1 && ld->unique_out() == shl) // Replace zero-extension-load with sign-extension-load return new (phase->C) LoadSNode( ld->in(MemNode::Control), - ld->in(MemNode::Memory), - ld->in(MemNode::Address), - ld->adr_type()); + ld->in(MemNode::Memory), + ld->in(MemNode::Address), + ld->adr_type(), TypeInt::SHORT, + MemNode::unordered); } // Check for "(byte[i] <<24)>>24" which simply sign-extends diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 808f64d2d9a..ac432ea3ea7 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -106,24 +106,24 @@ Node *Parse::fetch_interpreter_state(int index, // Very similar to LoadNode::make, except we handle un-aligned longs and // doubles on Sparc. Intel can handle them just fine directly. Node *l; - switch( bt ) { // Signature is flattened - case T_INT: l = new (C) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break; - case T_FLOAT: l = new (C) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break; - case T_ADDRESS: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break; - case T_OBJECT: l = new (C) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break; + switch (bt) { // Signature is flattened + case T_INT: l = new (C) LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT, MemNode::unordered); break; + case T_FLOAT: l = new (C) LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT, MemNode::unordered); break; + case T_ADDRESS: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered); break; + case T_OBJECT: l = new (C) LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM, MemNode::unordered); break; case T_LONG: case T_DOUBLE: { // Since arguments are in reverse order, the argument address 'adr' // refers to the back half of the long/double. Recompute adr. - adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize ); - if( Matcher::misaligned_doubles_ok ) { + adr = basic_plus_adr(local_addrs_base, local_addrs, -(index+1)*wordSize); + if (Matcher::misaligned_doubles_ok) { l = (bt == T_DOUBLE) - ? (Node*)new (C) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM ) - : (Node*)new (C) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); + ? (Node*)new (C) LoadDNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::DOUBLE, MemNode::unordered) + : (Node*)new (C) LoadLNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeLong::LONG, MemNode::unordered); } else { l = (bt == T_DOUBLE) - ? (Node*)new (C) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM ) - : (Node*)new (C) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); + ? (Node*)new (C) LoadD_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered) + : (Node*)new (C) LoadL_unalignedNode(ctl, mem, adr, TypeRawPtr::BOTTOM, MemNode::unordered); } break; } @@ -229,7 +229,7 @@ void Parse::load_interpreter_state(Node* osr_buf) { Node *displaced_hdr = fetch_interpreter_state((index*2) + 1, T_ADDRESS, monitors_addr, osr_buf); - store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw); + store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered); // Build a bogus FastLockNode (no code will be generated) and push the // monitor into our debug info. @@ -1931,7 +1931,7 @@ void Parse::call_register_finalizer() { Node* klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS) ); Node* access_flags_addr = basic_plus_adr(klass, klass, in_bytes(Klass::access_flags_offset())); - Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT); + Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT, MemNode::unordered); Node* mask = _gvn.transform(new (C) AndINode(access_flags, intcon(JVM_ACC_HAS_FINALIZER))); Node* check = _gvn.transform(new (C) CmpINode(mask, intcon(0))); diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 74119ef9f51..848a8f4a20c 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -50,7 +50,7 @@ void Parse::array_load(BasicType elem_type) { if (stopped()) return; // guaranteed null or range check dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); - Node* ld = make_load(control(), adr, elem, elem_type, adr_type); + Node* ld = make_load(control(), adr, elem, elem_type, adr_type, MemNode::unordered); push(ld); } @@ -62,7 +62,7 @@ void Parse::array_store(BasicType elem_type) { Node* val = pop(); dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); - store_to_memory(control(), adr, val, elem_type, adr_type); + store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); } @@ -1720,14 +1720,14 @@ void Parse::do_one_bytecode() { a = array_addressing(T_LONG, 0); if (stopped()) return; // guaranteed null or range check dec_sp(2); // Pop array and index - push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS)); + push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS, MemNode::unordered)); break; } case Bytecodes::_daload: { a = array_addressing(T_DOUBLE, 0); if (stopped()) return; // guaranteed null or range check dec_sp(2); // Pop array and index - push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES)); + push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered)); break; } case Bytecodes::_bastore: array_store(T_BYTE); break; @@ -1744,7 +1744,7 @@ void Parse::do_one_bytecode() { a = pop(); // the array itself const TypeOopPtr* elemtype = _gvn.type(a)->is_aryptr()->elem()->make_oopptr(); const TypeAryPtr* adr_type = TypeAryPtr::OOPS; - Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT); + Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, MemNode::release); break; } case Bytecodes::_lastore: { @@ -1752,7 +1752,7 @@ void Parse::do_one_bytecode() { if (stopped()) return; // guaranteed null or range check c = pop_pair(); dec_sp(2); // Pop array and index - store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS); + store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS, MemNode::unordered); break; } case Bytecodes::_dastore: { @@ -1761,7 +1761,7 @@ void Parse::do_one_bytecode() { c = pop_pair(); dec_sp(2); // Pop array and index c = dstore_rounding(c); - store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES); + store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered); break; } case Bytecodes::_getfield: diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 8c545f3ece5..a1b0929af79 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -228,7 +228,9 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { type = Type::get_const_basic_type(bt); } // Build the load. - Node* ld = make_load(NULL, adr, type, bt, adr_type, is_vol); + // + MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; + Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, is_vol); // Adjust Java stack if (type2size[bt] == 1) @@ -288,6 +290,16 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { // Round doubles before storing if (bt == T_DOUBLE) val = dstore_rounding(val); + // Conservatively release stores of object references. + const MemNode::MemOrd mo = + is_vol ? + // Volatile fields need releasing stores. + MemNode::release : + // Non-volatile fields also need releasing stores if they hold an + // object reference, because the object reference might point to + // a freshly created object. + StoreNode::release_if_reference(bt); + // Store the value. Node* store; if (bt == T_OBJECT) { @@ -297,9 +309,9 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { } else { field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); } - store = store_oop_to_object( control(), obj, adr, adr_type, val, field_type, bt); + store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo); } else { - store = store_to_memory( control(), adr, val, bt, adr_type, is_vol ); + store = store_to_memory(control(), adr, val, bt, adr_type, mo, is_vol); } // If reference is volatile, prevent following volatiles ops from @@ -414,7 +426,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs); intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop); Node* eaddr = basic_plus_adr(array, offset); - store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT); + store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, MemNode::unordered); } } return array; @@ -503,7 +515,7 @@ void Parse::do_multianewarray() { // Fill-in it with values for (j = 0; j < ndimensions; j++) { Node *dims_elem = array_element_address(dims, intcon(j), T_INT); - store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS); + store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS, MemNode::unordered); } } diff --git a/hotspot/src/share/vm/opto/parseHelper.cpp b/hotspot/src/share/vm/opto/parseHelper.cpp index 43d58e79546..729a038d873 100644 --- a/hotspot/src/share/vm/opto/parseHelper.cpp +++ b/hotspot/src/share/vm/opto/parseHelper.cpp @@ -222,7 +222,7 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) { Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset())); Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); - Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); + Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS, MemNode::unordered); Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); @@ -232,7 +232,7 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) { adr_node = basic_plus_adr(kls, kls, init_state_offset); // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler // can generate code to load it as unsigned byte. - Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN); + Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered); Node* being_init = _gvn.intcon(InstanceKlass::being_initialized); tst = Bool( CmpI( init_state, being_init), BoolTest::eq); iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); @@ -354,13 +354,13 @@ void Parse::increment_and_test_invocation_counter(int limit) { Node *counters_node = makecon(adr_type); Node* adr_iic_node = basic_plus_adr(counters_node, counters_node, MethodCounters::interpreter_invocation_counter_offset_in_bytes()); - Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type); + Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); test_counter_against_threshold(cnt, limit); // Add one to the counter and store Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); - store_to_memory( ctrl, adr_iic_node, incr, T_INT, adr_type ); + store_to_memory(ctrl, adr_iic_node, incr, T_INT, adr_type, MemNode::unordered); } //----------------------------method_data_addressing--------------------------- @@ -392,9 +392,9 @@ void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteS Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride); const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); + Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment))); - store_to_memory(NULL, adr_node, incr, T_INT, adr_type ); + store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered); } //--------------------------test_for_osr_md_counter_at------------------------- @@ -402,7 +402,7 @@ void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, By Node* adr_node = method_data_addressing(md, data, counter_offset); const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); + Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); test_counter_against_threshold(cnt, limit); } @@ -412,9 +412,9 @@ void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_const Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset()); const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); - Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type); + Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type, MemNode::unordered); Node* incr = _gvn.transform(new (C) OrINode(flags, _gvn.intcon(flag_constant))); - store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type); + store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type, MemNode::unordered); } //----------------------------profile_taken_branch----------------------------- diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp index 0306bc24a23..b00bb881faa 100644 --- a/hotspot/src/share/vm/opto/stringopts.cpp +++ b/hotspot/src/share/vm/opto/stringopts.cpp @@ -1122,7 +1122,8 @@ Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) { return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()), type, T_OBJECT, - C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes()))); + C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())), + MemNode::unordered); } Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { @@ -1314,7 +1315,7 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N Node* ch = __ AddI(r, __ intcon('0')); Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), - ch, T_CHAR, char_adr_idx); + ch, T_CHAR, char_adr_idx, MemNode::unordered); IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), @@ -1356,7 +1357,7 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N } else { Node* m1 = __ SubI(charPos, __ intcon(1)); Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), - sign, T_CHAR, char_adr_idx); + sign, T_CHAR, char_adr_idx, MemNode::unordered); final_merge->init_req(1, kit.control()); final_mem->init_req(1, st); @@ -1387,7 +1388,8 @@ Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, N ciTypeArray* value_array = t->const_oop()->as_type_array(); for (int e = 0; e < c; e++) { __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), - __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx); + __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx, + MemNode::unordered); start = __ AddI(start, __ intcon(1)); } } else { @@ -1607,7 +1609,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { } case StringConcat::CharMode: { __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), - arg, T_CHAR, char_adr_idx); + arg, T_CHAR, char_adr_idx, MemNode::unordered); start = __ AddI(start, __ intcon(1)); break; } diff --git a/hotspot/src/share/vm/opto/vectornode.hpp b/hotspot/src/share/vm/opto/vectornode.hpp index ba84406f1d7..0b95a10d8a6 100644 --- a/hotspot/src/share/vm/opto/vectornode.hpp +++ b/hotspot/src/share/vm/opto/vectornode.hpp @@ -356,7 +356,7 @@ class XorVNode : public VectorNode { class LoadVectorNode : public LoadNode { public: LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt) - : LoadNode(c, mem, adr, at, vt) { + : LoadNode(c, mem, adr, at, vt, MemNode::unordered) { init_class_id(Class_LoadVector); } @@ -380,7 +380,7 @@ class LoadVectorNode : public LoadNode { class StoreVectorNode : public StoreNode { public: StoreVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, Node* val) - : StoreNode(c, mem, adr, at, val) { + : StoreNode(c, mem, adr, at, val, MemNode::unordered) { assert(val->is_Vector() || val->is_LoadVector(), "sanity"); init_class_id(Class_StoreVector); } From f9a0d6a4b523188e22c70c580051671d64fd71a5 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 15 Nov 2013 12:01:00 -0800 Subject: [PATCH 033/265] 8028401: PPC (part 117): Improve usability of adlc and format() functionality Add additional, more verbose syntax checks in adlc. Fix printing constant's problem in format(). Reviewed-by: kvn --- hotspot/src/share/vm/adlc/adlparse.cpp | 35 +++++++++++++++++++------- hotspot/src/share/vm/adlc/formssel.cpp | 4 +-- hotspot/src/share/vm/adlc/output_c.cpp | 29 +++++++++++++++++---- hotspot/src/share/vm/opto/machnode.cpp | 3 +++ hotspot/src/share/vm/opto/machnode.hpp | 2 ++ 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 175bd04cfa2..dd303a37aff 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -3996,13 +3996,11 @@ void ADLParser::effect_parse(InstructForm *instr) { //------------------------------expand_parse----------------------------------- ExpandRule* ADLParser::expand_parse(InstructForm *instr) { char *ident, *ident2; - OperandForm *oper; - InstructForm *ins; NameAndList *instr_and_operands = NULL; ExpandRule *exp = new ExpandRule(); - // Expand is a block containing an ordered list of instructions, each of - // which has an ordered list of operands. + // Expand is a block containing an ordered list of operands with initializers, + // or instructions, each of which has an ordered list of operands. // Check for block delimiter skipws(); // Skip leading whitespace if ((_curchar != '%') @@ -4016,12 +4014,30 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { if (ident == NULL) { parse_err(SYNERR, "identifier expected at %c\n", _curchar); continue; - } // Check that you have a valid instruction + } + + // Check whether we should parse an instruction or operand. const Form *form = _globalNames[ident]; - ins = form ? form->is_instruction() : NULL; - if (ins == NULL) { + bool parse_oper = false; + bool parse_ins = false; + if (form == NULL) { + skipws(); + // Check whether this looks like an instruction specification. If so, + // just parse the instruction. The declaration of the instruction is + // not needed here. + if (_curchar == '(') parse_ins = true; + } else if (form->is_instruction()) { + parse_ins = true; + } else if (form->is_operand()) { + parse_oper = true; + } else { + parse_err(SYNERR, "instruction/operand name expected at %s\n", ident); + continue; + } + + if (parse_oper) { // This is a new operand - oper = form ? form->is_operand() : NULL; + OperandForm *oper = form->is_operand(); if (oper == NULL) { parse_err(SYNERR, "instruction/operand name expected at %s\n", ident); continue; @@ -4056,6 +4072,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { skipws(); } else { + assert(parse_ins, "sanity"); // Add instruction to list instr_and_operands = new NameAndList(ident); // Grab operands, build nameList of them, and then put into dictionary @@ -4079,7 +4096,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { parse_err(SYNERR, "operand name expected at %s\n", ident2); continue; } - oper = form2->is_operand(); + OperandForm *oper = form2->is_operand(); if (oper == NULL && !form2->is_opclass()) { parse_err(SYNERR, "operand name expected at %s\n", ident2); continue; diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 2e1e341c9df..ff9351242ba 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -1276,11 +1276,11 @@ void InstructForm::rep_var_format(FILE *fp, const char *rep_var) { return; } if (strcmp(rep_var, "constantoffset") == 0) { - fprintf(fp, "st->print(\"#%%d\", constant_offset());\n"); + fprintf(fp, "st->print(\"#%%d\", constant_offset_unchecked());\n"); return; } if (strcmp(rep_var, "constantaddress") == 0) { - fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset());\n"); + fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset_unchecked());\n"); return; } diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index 53a09d9eb98..dda0afd070e 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1570,6 +1570,13 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { new_id = expand_instr->name(); InstructForm* expand_instruction = (InstructForm*)globalAD->globalNames()[new_id]; + + if (!expand_instruction) { + globalAD->syntax_err(node->_linenum, "In %s: instruction %s used in expand not declared\n", + node->_ident, new_id); + continue; + } + if (expand_instruction->has_temps()) { globalAD->syntax_err(node->_linenum, "In %s: expand rules using instructs with TEMPs aren't supported: %s", node->_ident, new_id); @@ -1628,6 +1635,13 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { // Use 'parameter' at current position in list of new instruction's formals // instead of 'opid' when looking up info internal to new_inst const char *parameter = formal_lst->iter(); + if (!parameter) { + globalAD->syntax_err(node->_linenum, "Operand %s of expand instruction %s has" + " no equivalent in new instruction %s.", + opid, node->_ident, new_inst->_ident); + assert(0, "Wrong expand"); + } + // Check for an operand which is created in the expand rule if ((exp_pos = node->_exprule->_newopers.index(opid)) != -1) { new_pos = new_inst->operand_position(parameter,Component::USE); @@ -2103,16 +2117,21 @@ public: if (strcmp(rep_var,"$reg") == 0 || reg_conversion(rep_var) != NULL) { _reg_status = LITERAL_ACCESSED; } else { + _AD.syntax_err(_encoding._linenum, + "Invalid access to literal register parameter '%s' in %s.\n", + rep_var, _encoding._name); assert( false, "invalid access to literal register parameter"); } } // literal constant parameters must be accessed as a 'constant' field - if ( _constant_status != LITERAL_NOT_SEEN ) { - assert( _constant_status == LITERAL_SEEN, "Must have seen constant literal before now"); - if( strcmp(rep_var,"$constant") == 0 ) { - _constant_status = LITERAL_ACCESSED; + if (_constant_status != LITERAL_NOT_SEEN) { + assert(_constant_status == LITERAL_SEEN, "Must have seen constant literal before now"); + if (strcmp(rep_var,"$constant") == 0) { + _constant_status = LITERAL_ACCESSED; } else { - assert( false, "invalid access to literal constant parameter"); + _AD.syntax_err(_encoding._linenum, + "Invalid access to literal constant parameter '%s' in %s.\n", + rep_var, _encoding._name); } } } // end replacement and/or subfield diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index a1bcda9599f..2777058c279 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -505,6 +505,9 @@ int MachConstantNode::constant_offset() { return _constant.offset(); } +int MachConstantNode::constant_offset_unchecked() const { + return _constant.offset(); +} //============================================================================= #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 44d45ca8040..c3ac46a533d 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -416,6 +416,8 @@ public: int constant_offset(); int constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); } + // Unchecked version to avoid assertions in debug output. + int constant_offset_unchecked() const; }; //------------------------------MachUEPNode----------------------------------- From c16bc98686431713ccfb102514be72ce08c66b7d Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Sat, 16 Nov 2013 01:42:55 +0100 Subject: [PATCH 034/265] 8028470: PPC64 (part 214): linux: extend signal handler to catch SIGTRAP on ppc64 Reviewed-by: kvn --- hotspot/src/os/linux/vm/os_linux.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3522f090e8c..349ab78ea62 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -532,6 +532,9 @@ void os::Linux::signal_sets_init() { sigaddset(&unblocked_sigs, SIGSEGV); sigaddset(&unblocked_sigs, SIGBUS); sigaddset(&unblocked_sigs, SIGFPE); +#if defined(PPC64) + sigaddset(&unblocked_sigs, SIGTRAP); +#endif sigaddset(&unblocked_sigs, SR_signum); if (!ReduceSignalUsage) { @@ -2294,6 +2297,9 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); print_signal_handler(st, BREAK_SIGNAL, buf, buflen); +#if defined(PPC64) + print_signal_handler(st, SIGTRAP, buf, buflen); +#endif } static char saved_jvm_path[MAXPATHLEN] = {0}; @@ -4423,6 +4429,9 @@ void os::Linux::install_signal_handlers() { set_signal_handler(SIGBUS, true); set_signal_handler(SIGILL, true); set_signal_handler(SIGFPE, true); +#if defined(PPC64) + set_signal_handler(SIGTRAP, true); +#endif set_signal_handler(SIGXFSZ, true); if (libjsig_is_loaded) { @@ -4565,7 +4574,9 @@ void os::run_periodic_checks() { DO_SIGNAL_CHECK(SIGBUS); DO_SIGNAL_CHECK(SIGPIPE); DO_SIGNAL_CHECK(SIGXFSZ); - +#if defined(PPC64) + DO_SIGNAL_CHECK(SIGTRAP); +#endif // ReduceSignalUsage allows the user to override these handlers // see comments at the very top and jvm_solaris.h From 86fba81619ec41922220448cbb5cdaec537d65bd Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Tue, 19 Nov 2013 11:53:58 -0800 Subject: [PATCH 035/265] 8028514: PPC64: Fix C++ Interpreter after '7195622: CheckUnhandledOops has limited usefulness now' Fix CPP-interpreter after CheckUnhandledOops was re-enabled in the fastdebug build Reviewed-by: kvn, dholmes, lfoltan --- hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp | 2 +- hotspot/src/cpu/ppc/vm/frame_ppc.cpp | 2 +- hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp | 4 ++-- .../src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp | 2 +- hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.hpp | 2 +- hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp | 2 +- .../src/share/vm/interpreter/bytecodeInterpreter.cpp | 12 ++++++------ hotspot/src/share/vm/oops/methodData.hpp | 6 +++--- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp index 3706c984b37..038854f6d2c 100644 --- a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp @@ -91,7 +91,7 @@ public: #define LOCALS_SLOT(offset) ((intptr_t*)&locals[-(offset)]) #define LOCALS_ADDR(offset) ((address)locals[-(offset)]) #define LOCALS_INT(offset) (*(jint*)&(locals[-(offset)])) -#define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) +#define LOCALS_OBJECT(offset) (cast_to_oop(locals[-(offset)])) #define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)])) #define LOCALS_DOUBLE_AT(offset) (((address)&locals[-((offset) + 1)])) diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp index 03d525db4e3..2800635adf8 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp @@ -188,7 +188,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) case T_OBJECT: case T_ARRAY: { oop* obj_p = *(oop**)lresult; - oop obj = (obj_p == NULL) ? NULL : *obj_p; + oop obj = (obj_p == NULL) ? (oop)NULL : *obj_p; assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); *oop_result = obj; break; diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp index 5b88284b2df..fecb5813384 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp @@ -188,7 +188,7 @@ intptr_t NativeMovConstReg::data() const { return MacroAssembler::get_const(addr); } else if (MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) { narrowOop no = (narrowOop)MacroAssembler::get_narrow_oop(addr, cb->content_begin()); - return (intptr_t)oopDesc::decode_heap_oop(no); + return cast_from_oop(oopDesc::decode_heap_oop(no)); } else { assert(MacroAssembler::is_load_const_from_method_toc_at(addr), "must be load_const_from_pool"); @@ -258,7 +258,7 @@ void NativeMovConstReg::set_data(intptr_t data) { oop_Relocation *r = iter.oop_reloc(); if (oop_addr == NULL) { oop_addr = r->oop_addr(); - *oop_addr = (oop)data; + *oop_addr = cast_to_oop(data); } else { assert(oop_addr == r->oop_addr(), "must be only one set-oop here") ; } diff --git a/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp index aad5bc7162c..dd417a30eb5 100644 --- a/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp @@ -83,7 +83,7 @@ public: #define LOCALS_ADDR(offset) ((address)locals[-(offset)]) #define LOCALS_INT(offset) (*((jint*)&locals[-(offset)])) #define LOCALS_FLOAT(offset) (*((jfloat*)&locals[-(offset)])) -#define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) +#define LOCALS_OBJECT(offset) (cast_to_oop(locals[-(offset)])) #define LOCALS_DOUBLE(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->d) #define LOCALS_LONG(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->l) #define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)])) diff --git a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.hpp b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.hpp index e4eaa751286..2538b4ef451 100644 --- a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.hpp +++ b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.hpp @@ -94,7 +94,7 @@ inline intptr_t* sender_sp() { #define LOCALS_ADDR(offset) ((address)locals[-(offset)]) #define LOCALS_INT(offset) ((jint)(locals[-(offset)])) #define LOCALS_FLOAT(offset) (*((jfloat*)&locals[-(offset)])) -#define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) +#define LOCALS_OBJECT(offset) (cast_to_oop(locals[-(offset)])) #define LOCALS_DOUBLE(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->d) #define LOCALS_LONG(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->l) #define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)])) diff --git a/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp index 0b355b5c5b2..f7bcb91e547 100644 --- a/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/bytecodeInterpreter_zero.hpp @@ -132,7 +132,7 @@ #define LOCALS_ADDR(offset) ((address)locals[-(offset)]) #define LOCALS_INT(offset) (*((jint*)&locals[-(offset)])) #define LOCALS_FLOAT(offset) (*((jfloat*)&locals[-(offset)])) -#define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) +#define LOCALS_OBJECT(offset) (cast_to_oop(locals[-(offset)])) #define LOCALS_DOUBLE(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->d) #define LOCALS_LONG(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->l) #define LOCALS_LONG_AT(offset) (((address)&locals[-((offset) + 1)])) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 6008fdd6e1c..6b9dd574b30 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1810,7 +1810,7 @@ run: // Profile checkcast with null_seen and receiver. BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL); } - ((objArrayOopDesc *) arrObj)->obj_at_put(index, rhsObject); + ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } CASE(_bastore): @@ -2828,7 +2828,7 @@ run: if (TraceExceptions) { ttyLocker ttyl; ResourceMark rm; - tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, continuing at %d for thread " INTPTR_FORMAT, istate->bcp() - (intptr_t)METHOD->code_base(), @@ -2844,7 +2844,7 @@ run: if (TraceExceptions) { ttyLocker ttyl; ResourceMark rm; - tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), except_oop()); + tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", except_oop->print_value_string(), (void*)except_oop()); tty->print_cr(" thrown in interpreter method <%s>", METHOD->print_value_string()); tty->print_cr(" at bci %d, unwinding for thread " INTPTR_FORMAT, istate->bcp() - (intptr_t)METHOD->code_base(), @@ -3213,7 +3213,7 @@ jfloat BytecodeInterpreter::stack_float(intptr_t *tos, int offset) { } oop BytecodeInterpreter::stack_object(intptr_t *tos, int offset) { - return (oop)tos [Interpreter::expr_index_at(-offset)]; + return cast_to_oop(tos [Interpreter::expr_index_at(-offset)]); } jdouble BytecodeInterpreter::stack_double(intptr_t *tos, int offset) { @@ -3282,7 +3282,7 @@ jfloat BytecodeInterpreter::locals_float(intptr_t* locals, int offset) { return (jfloat)locals[Interpreter::local_index_at(-offset)]; } oop BytecodeInterpreter::locals_object(intptr_t* locals, int offset) { - return (oop)locals[Interpreter::local_index_at(-offset)]; + return cast_to_oop(locals[Interpreter::local_index_at(-offset)]); } jdouble BytecodeInterpreter::locals_double(intptr_t* locals, int offset) { return ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->d; @@ -3441,7 +3441,7 @@ BytecodeInterpreter::print() { tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf); tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry); tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link); - tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp); + tty->print_cr("native_mirror: " INTPTR_FORMAT, (void*) this->_oop_temp); tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base); tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit); tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base); diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 8846ef74064..03c96f24d81 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -395,7 +395,7 @@ protected: } static oop oop_at(DataLayout* layout, int index) { - return (oop)layout->cell_at(index); + return cast_to_oop(layout->cell_at(index)); } static void set_intptr_at(DataLayout* layout, int index, intptr_t value) { @@ -1248,8 +1248,8 @@ public: } static Klass *receiver_unchecked(DataLayout* layout, uint row) { - oop recv = oop_at(layout, receiver_cell_index(row)); - return (Klass *)recv; + Klass* recv = (Klass*)layout->cell_at(receiver_cell_index(row)); + return recv; } static void increment_receiver_count_no_overflow(DataLayout* layout, Klass *rcvr) { From d22bde2c913e289df59a6dbf06e231ade5b0ef1a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 20 Nov 2013 11:08:09 -0800 Subject: [PATCH 036/265] 8028580: PPC64 (part 114/120): Support for Call nodes with constants Extends MachCall nodes so that they can issue constants to the constant table Reviewed-by: kvn --- hotspot/src/share/vm/adlc/adlparse.cpp | 50 ++++++++++++++++++-------- hotspot/src/share/vm/adlc/formssel.cpp | 2 ++ hotspot/src/share/vm/adlc/formssel.hpp | 5 ++- hotspot/src/share/vm/adlc/output_c.cpp | 15 +++++--- hotspot/src/share/vm/adlc/output_h.cpp | 8 ++++- hotspot/src/share/vm/opto/machnode.cpp | 16 +++++++-- hotspot/src/share/vm/opto/machnode.hpp | 8 ++++- hotspot/src/share/vm/opto/output.cpp | 8 +++-- 8 files changed, 85 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index dd303a37aff..d6c58718b58 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -2863,7 +2863,10 @@ void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encodi // Check if this instruct is a MachConstantNode. if (strcmp(rep_var, "constanttablebase") == 0) { // This instruct is a MachConstantNode. - inst.set_is_mach_constant(true); + inst.set_needs_constant_base(true); + if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) { + inst.set_is_mach_constant(true); + } if (_curchar == '(') { parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument " @@ -2965,18 +2968,34 @@ void ADLParser::ins_encode_parse(InstructForm& inst) { while (_curchar != ')') { char *param = get_ident_or_literal_constant("encoding operand"); if ( param != NULL ) { - // Found a parameter: - // Check it is a local name, add it to the list, then check for more - // New: allow hex constants as parameters to an encode method. - // New: allow parenthesized expressions as parameters. - // New: allow "primary", "secondary", "tertiary" as parameters. - // New: allow user-defined register name as parameter - if ( (inst._localNames[param] == NULL) && - !ADLParser::is_literal_constant(param) && - (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && - ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) { - parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); - return; + + // Check if this instruct is a MachConstantNode. + if (strcmp(param, "constanttablebase") == 0) { + // This instruct is a MachConstantNode. + inst.set_needs_constant_base(true); + if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) { + inst.set_is_mach_constant(true); + } + + if (_curchar == '(') { + parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument " + "(only constantaddress and constantoffset)", ec_name); + return; + } + } else { + // Found a parameter: + // Check it is a local name, add it to the list, then check for more + // New: allow hex constants as parameters to an encode method. + // New: allow parenthesized expressions as parameters. + // New: allow "primary", "secondary", "tertiary" as parameters. + // New: allow user-defined register name as parameter + if ( (inst._localNames[param] == NULL) && + !ADLParser::is_literal_constant(param) && + (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && + ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) { + parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); + return; + } } params->add_entry(param); @@ -3122,7 +3141,10 @@ void ADLParser::postalloc_expand_parse(InstructForm& inst) { // Check if this instruct is a MachConstantNode. if (strcmp(param, "constanttablebase") == 0) { // This instruct is a MachConstantNode. - inst.set_is_mach_constant(true); + inst.set_needs_constant_base(true); + if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) { + inst.set_is_mach_constant(true); + } if (_curchar == '(') { parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument " diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index ff9351242ba..b20835815e3 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -32,6 +32,7 @@ InstructForm::InstructForm(const char *id, bool ideal_only) _localNames(cmpstr, hashstr, Form::arena), _effects(cmpstr, hashstr, Form::arena), _is_mach_constant(false), + _needs_constant_base(false), _has_call(false) { _ftype = Form::INS; @@ -65,6 +66,7 @@ InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule) _localNames(instr->_localNames), _effects(instr->_effects), _is_mach_constant(false), + _needs_constant_base(false), _has_call(false) { _ftype = Form::INS; diff --git a/hotspot/src/share/vm/adlc/formssel.hpp b/hotspot/src/share/vm/adlc/formssel.hpp index 0fafe44c953..2a9cfa45b31 100644 --- a/hotspot/src/share/vm/adlc/formssel.hpp +++ b/hotspot/src/share/vm/adlc/formssel.hpp @@ -83,7 +83,8 @@ private: const char *_cisc_reg_mask_name; InstructForm *_short_branch_form; bool _is_short_branch; - bool _is_mach_constant; // true if Node is a MachConstantNode + bool _is_mach_constant; // True if Node is a MachConstantNode. + bool _needs_constant_base; // True if Node needs the mach_constant_base input. uint _alignment; public: @@ -262,6 +263,8 @@ public: bool is_mach_constant() const { return _is_mach_constant; } void set_is_mach_constant(bool x) { _is_mach_constant = x; } + bool needs_constant_base() const { return _needs_constant_base; } + void set_needs_constant_base(bool x) { _needs_constant_base = x; } InstructForm *short_branch_form() { return _short_branch_form; } bool has_short_branch_form() { return _short_branch_form != NULL; } diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index dda0afd070e..a6c3bcbf789 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1839,7 +1839,9 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { // If the node is a MachConstantNode, insert the MachConstantBaseNode edge. // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input). - if (node->is_mach_constant()) { + // There are nodes that don't use $constantablebase, but still require that it + // is an input to the node. Example: divF_reg_immN, Repl32B_imm on x86_64. + if (node->is_mach_constant() || node->needs_constant_base()) { fprintf(fp," add_req(C->mach_constant_base_node());\n"); } @@ -1952,9 +1954,9 @@ public: else if ((strcmp(rep_var, "constanttablebase") == 0) || (strcmp(rep_var, "constantoffset") == 0) || (strcmp(rep_var, "constantaddress") == 0)) { - if (!_inst.is_mach_constant()) { + if (!(_inst.is_mach_constant() || _inst.needs_constant_base())) { _AD.syntax_err(_encoding._linenum, - "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n", + "Replacement variable %s not allowed in instruct %s (only in MachConstantNode or MachCall).\n", rep_var, _encoding._name); } } @@ -3182,6 +3184,7 @@ void ArchDesc::defineClasses(FILE *fp) { if( instr->expands() || instr->needs_projections() || instr->has_temps() || instr->is_mach_constant() || + instr->needs_constant_base() || instr->_matrule != NULL && instr->num_opnds() != instr->num_unique_opnds() ) defineExpand(_CPP_EXPAND_file._fp, instr); @@ -3954,8 +3957,10 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden } // Fill in the bottom_type where requested - if ( inst->captures_bottom_type(_globalNames) ) { - fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); + if (inst->captures_bottom_type(_globalNames)) { + if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall"))) { + fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent); + } } if( inst->is_ideal_if() ) { fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent); diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index a4624f12e38..4a72bb27983 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1614,7 +1614,7 @@ void ArchDesc::declareClasses(FILE *fp) { if (strcmp (attr->_ident,"ins_cost") && strncmp(attr->_ident,"ins_field_", 10) != 0 && strcmp (attr->_ident,"ins_short_branch")) { - fprintf(fp," int %s() const { return %s; }\n", + fprintf(fp," virtual int %s() const { return %s; }\n", attr->_ident, attr->_val); } // Check value for ins_avoid_back_to_back, and if it is true (1), set the flag @@ -1655,6 +1655,11 @@ void ArchDesc::declareClasses(FILE *fp) { instr->ideal_Opcode(_globalNames) ); } + if (instr->needs_constant_base() && + !instr->is_mach_constant()) { // These inherit the funcion from MachConstantNode. + fprintf(fp," virtual uint mach_constant_base_node_input() const { return req()-1; }\n"); + } + // Allow machine-independent optimization, invert the sense of the IF test if( instr->is_ideal_if() ) { fprintf(fp," virtual void negate() { \n"); @@ -1823,6 +1828,7 @@ void ArchDesc::declareClasses(FILE *fp) { if( instr->expands() || instr->needs_projections() || instr->has_temps() || instr->is_mach_constant() || + instr->needs_constant_base() || instr->_matrule != NULL && instr->num_opnds() != instr->num_unique_opnds() ) { fprintf(fp," virtual MachNode *Expand(State *state, Node_List &proj_list, Node* mem);\n"); diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 2777058c279..7411e183cee 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -648,10 +648,15 @@ bool MachCallNode::return_value_is_used() const { //------------------------------Registers-------------------------------------- -const RegMask &MachCallNode::in_RegMask( uint idx ) const { +const RegMask &MachCallNode::in_RegMask(uint idx) const { // Values in the domain use the users calling convention, embodied in the // _in_rms array of RegMasks. - if (idx < tf()->domain()->cnt()) return _in_rms[idx]; + if (idx < tf()->domain()->cnt()) { + return _in_rms[idx]; + } + if (idx == mach_constant_base_node_input()) { + return MachConstantBaseNode::static_out_RegMask(); + } // Values outside the domain represent debug info return *Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()]; } @@ -678,7 +683,12 @@ void MachCallJavaNode::dump_spec(outputStream *st) const { const RegMask &MachCallJavaNode::in_RegMask(uint idx) const { // Values in the domain use the users calling convention, embodied in the // _in_rms array of RegMasks. - if (idx < tf()->domain()->cnt()) return _in_rms[idx]; + if (idx < tf()->domain()->cnt()) { + return _in_rms[idx]; + } + if (idx == mach_constant_base_node_input()) { + return MachConstantBaseNode::static_out_RegMask(); + } // Values outside the domain represent debug info Matcher* m = Compile::current()->matcher(); // If this call is a MethodHandle invoke we have to use a different diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index c3ac46a533d..d5430194af6 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -181,6 +181,9 @@ public: // Number of inputs which come before the first operand. // Generally at least 1, to skip the Control input virtual uint oper_input_base() const { return 1; } + // Position of constant base node in node's inputs. -1 if + // no constant base node input. + virtual uint mach_constant_base_node_input() const { return (uint)-1; } // Copy inputs and operands to new node of instruction. // Called from cisc_version() and short_branch_version(). @@ -250,6 +253,9 @@ public: // Return number of relocatable values contained in this instruction virtual int reloc() const { return 0; } + // Return number of words used for double constants in this instruction + virtual int ins_num_consts() const { return 0; } + // Hash and compare over operands. Used to do GVN on machine Nodes. virtual uint hash() const; virtual uint cmp( const Node &n ) const; @@ -412,7 +418,7 @@ public: } // Input edge of MachConstantBaseNode. - uint mach_constant_base_node_input() const { return req() - 1; } + virtual uint mach_constant_base_node_input() const { return req() - 1; } int constant_offset(); int constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); } diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index eb2a2c15ee1..737632a7d93 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1083,6 +1083,7 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) { assert(_frame_slots >= 0 && _frame_slots < 1000000, "sanity check"); if (has_mach_constant_base_node()) { + uint add_size = 0; // Fill the constant table. // Note: This must happen before shorten_branches. for (uint i = 0; i < _cfg->number_of_blocks(); i++) { @@ -1096,6 +1097,9 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) { if (n->is_MachConstant()) { MachConstantNode* machcon = n->as_MachConstant(); machcon->eval_constant(C); + } else if (n->is_Mach()) { + // On Power there are more nodes that issue constants. + add_size += (n->as_Mach()->ins_num_consts() * 8); } } } @@ -1103,7 +1107,7 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) { // Calculate the offsets of the constants and the size of the // constant table (including the padding to the next section). constant_table().calculate_offsets_and_size(); - const_req = constant_table().size(); + const_req = constant_table().size() + add_size; } // Initialize the space for the BufferBlob used to find and verify @@ -1374,7 +1378,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { int offset = blk_starts[block_num] - current_offset; if (block_num >= i) { // Current and following block's offset are not - // finilized yet, adjust distance by the difference + // finalized yet, adjust distance by the difference // between calculated and final offsets of current block. offset -= (blk_starts[i] - blk_offset); } From a7c123880e2337f6bab4c29801a62abb0ffe0957 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 21 Nov 2013 18:29:34 -0800 Subject: [PATCH 037/265] 8028471: PPC64 (part 215): opto: Extend ImplicitNullCheck optimization Fixed Implicit NULL check optimization for AIX, where the page at address '0' is only write-protected. Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 2 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 2 +- .../cpu/ppc/vm/macroAssembler_ppc.inline.hpp | 6 +-- hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 2 +- hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 2 +- hotspot/src/os/bsd/vm/os_bsd.hpp | 3 ++ hotspot/src/os/linux/vm/os_linux.hpp | 3 ++ hotspot/src/os/solaris/vm/os_solaris.hpp | 3 ++ hotspot/src/os/windows/vm/os_windows.hpp | 3 ++ hotspot/src/share/vm/opto/callGenerator.cpp | 2 +- hotspot/src/share/vm/opto/lcm.cpp | 45 +++++++++++++++++++ 11 files changed, 65 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index 2dd4b1df167..b39151004c9 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -92,7 +92,7 @@ define_pd_global(uintx, TypeProfileLevel, 0); /* Trap based checks use the ppc trap instructions to check certain */ \ /* conditions. This instruction raises a SIGTRAP caught by the */ \ /* exception handler of the VM. */ \ - product(bool, UseSIGTRAP, false, \ + product(bool, UseSIGTRAP, true, \ "Allow trap instructions that make use of SIGTRAP. Use this to " \ "switch off all optimizations requiring SIGTRAP.") \ product(bool, TrapBasedICMissChecks, true, \ diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index eb716b5b84e..f4b7c5e7652 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -2433,7 +2433,7 @@ void MacroAssembler::load_klass(Register dst, Register src) { } void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) { - if (false NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (!os::zero_page_read_protected()) { if (TrapBasedNullChecks) { trap_null_check(src); } diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp index d80e4ec4459..529f82468ef 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp @@ -269,7 +269,7 @@ inline void MacroAssembler::trap_ic_miss_check(Register a, Register b) { // No support for compressed oops (base page of heap). Does not distinguish // loads and stores. inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, address exception_entry) { - if (!ImplicitNullChecks || needs_explicit_null_check(offset) NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { assert(UseSIGTRAP, "sanity"); trap_null_check(a); @@ -286,7 +286,7 @@ inline void MacroAssembler::null_check_throw(Register a, int offset, Register te } inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Register s1) { - if ( NOT_LINUX(true) LINUX_ONLY(false)/*!os::zero_page_read_protected()*/) { + if (!os::zero_page_read_protected()) { if (TrapBasedNullChecks) { trap_null_check(s1); } @@ -297,7 +297,7 @@ inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Regist // Attention: No null check for loaded uncompressed OOP. Can be used for loading klass field. inline void MacroAssembler::load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant si16, Register s1) { - if ( NOT_LINUX(true)LINUX_ONLY(false) /*!os::zero_page_read_protected()*/) { + if ( !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { trap_null_check(s1); } diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index e9d21760130..c2a971118cf 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -1128,7 +1128,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "klass offset should reach into any page"); // Check for NULL argument if we don't have implicit null checks. - if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (!ImplicitNullChecks || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { __ trap_null_check(R3_ARG1); } else { diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp index 5323e4ae59e..6a608e93262 100644 --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -221,7 +221,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { // Must do an explicit check if implicit checks are disabled. assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity"); - if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) { + if (!ImplicitNullChecks || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { __ trap_null_check(R19_method); } else { diff --git a/hotspot/src/os/bsd/vm/os_bsd.hpp b/hotspot/src/os/bsd/vm/os_bsd.hpp index a906a30e97f..c33968a0ab3 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp @@ -27,6 +27,9 @@ // Bsd_OS defines the interface to Bsd operating systems +// Information about the protection of the page at address '0' on this os. +static bool zero_page_read_protected() { return true; } + /* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */ typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 5eed54f8c1e..829852f9195 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -30,6 +30,9 @@ /* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */ typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); +// Information about the protection of the page at address '0' on this os. +static bool zero_page_read_protected() { return true; } + class Linux { friend class os; friend class TestReserveMemorySpecial; diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 330d4fbc591..0485346914a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -27,6 +27,9 @@ // Solaris_OS defines the interface to Solaris operating systems +// Information about the protection of the page at address '0' on this os. +static bool zero_page_read_protected() { return true; } + class Solaris { friend class os; diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp index 67ed8a4af7c..c9c4840bb6c 100644 --- a/hotspot/src/os/windows/vm/os_windows.hpp +++ b/hotspot/src/os/windows/vm/os_windows.hpp @@ -26,6 +26,9 @@ #define OS_WINDOWS_VM_OS_WINDOWS_HPP // Win32_OS defines the interface to windows operating systems +// Information about the protection of the page at address '0' on this os. +static bool zero_page_read_protected() { return true; } + class win32 { friend class os; diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index adc27ac02e4..22807e2c700 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -201,7 +201,7 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { // Block::implicit_null_check() only looks for loads and stores, not calls. ciMethod *caller = kit.method(); ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data(); - if (!UseInlineCaches || !ImplicitNullChecks || + if (!UseInlineCaches || !ImplicitNullChecks || !os::zero_page_read_protected() || ((ImplicitNullCheckThreshold > 0) && caller_md && (caller_md->trap_count(Deoptimization::Reason_null_check) >= (uint)ImplicitNullCheckThreshold))) { diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 8c4f339cd3f..dfdc663a2cb 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -54,6 +54,43 @@ // Optimization - Graph Style +// Check whether val is not-null-decoded compressed oop, +// i.e. will grab into the base of the heap if it represents NULL. +static bool accesses_heap_base_zone(Node *val) { + if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops. + if (val && val->is_Mach()) { + if (val->as_Mach()->ideal_Opcode() == Op_DecodeN) { + // This assumes all Decodes with TypePtr::NotNull are matched to nodes that + // decode NULL to point to the heap base (Decode_NN). + if (val->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull) { + return true; + } + } + // Must recognize load operation with Decode matched in memory operand. + // We should not reach here exept for PPC/AIX, as os::zero_page_read_protected() + // returns true everywhere else. On PPC, no such memory operands + // exist, therefore we did not yet implement a check for such operands. + NOT_AIX(Unimplemented()); + } + } + return false; +} + +static bool needs_explicit_null_check_for_read(Node *val) { + // On some OSes (AIX) the page at address 0 is only write protected. + // If so, only Store operations will trap. + if (os::zero_page_read_protected()) { + return false; // Implicit null check will work. + } + // Also a read accessing the base of a heap-based compressed heap will trap. + if (accesses_heap_base_zone(val) && // Hits the base zone page. + Universe::narrow_oop_use_implicit_null_checks()) { // Base zone page is protected. + return false; + } + + return true; +} + //------------------------------implicit_null_check---------------------------- // Detect implicit-null-check opportunities. Basically, find NULL checks // with suitable memory ops nearby. Use the memory op to do the NULL check. @@ -209,6 +246,14 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo } break; } + + // On some OSes (AIX) the page at address 0 is only write protected. + // If so, only Store operations will trap. + // But a read accessing the base of a heap-based compressed heap will trap. + if (!was_store && needs_explicit_null_check_for_read(val)) { + continue; + } + // check if the offset is not too high for implicit exception { intptr_t offset = 0; From 7289ee4573764a592c51465a624cb447142839d3 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 21 Nov 2013 19:00:57 -0800 Subject: [PATCH 038/265] 8028767: PPC64: (part 121): smaller shared changes needed to build C2 Smaller shared changes required to build the C2 compiler on PPC64. Reviewed-by: kvn --- hotspot/src/share/vm/adlc/output_h.cpp | 4 ++++ hotspot/src/share/vm/asm/assembler.hpp | 3 ++- .../src/share/vm/compiler/compileBroker.cpp | 2 +- hotspot/src/share/vm/memory/metaspace.hpp | 3 +++ hotspot/src/share/vm/opto/c2_globals.hpp | 3 ++- hotspot/src/share/vm/opto/chaitin.cpp | 4 ++-- hotspot/src/share/vm/opto/machnode.cpp | 11 ++++++++++ hotspot/src/share/vm/opto/machnode.hpp | 2 ++ hotspot/src/share/vm/opto/regalloc.cpp | 4 +++- hotspot/src/share/vm/opto/type.cpp | 20 ++++++++++++------- hotspot/src/share/vm/opto/type.hpp | 3 +++ 11 files changed, 46 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 4a72bb27983..34a3ba9681a 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -26,7 +26,11 @@ #include "adlc.hpp" // The comment delimiter used in format statements after assembler instructions. +#if defined(PPC64) +#define commentSeperator "\t//" +#else #define commentSeperator "!" +#endif // Generate the #define that describes the number of registers. static void defineRegCount(FILE *fp, RegisterForm *registers) { diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index 8a9e2758a58..effe646d16d 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -204,10 +204,11 @@ class AbstractAssembler : public ResourceObj { CodeSection* _code_section; // section within the code buffer OopRecorder* _oop_recorder; // support for relocInfo::oop_type + public: // Code emission & accessing address addr_at(int pos) const { return code_section()->start() + pos; } - + protected: // This routine is called with a label is used for an address. // Labels and displacements truck in offsets, but target must return a PC. address target(Label& L) { return code_section()->target(L, pc()); } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 2963e85addd..f8fa26ff8c2 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -998,7 +998,7 @@ CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQue void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { EXCEPTION_MARK; -#if !defined(ZERO) && !defined(SHARK) && !defined(PPC64) +#if !defined(ZERO) && !defined(SHARK) assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); #endif // !ZERO && !SHARK // Initialize the compilation queue diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp index c22d2170761..30826d96564 100644 --- a/hotspot/src/share/vm/memory/metaspace.hpp +++ b/hotspot/src/share/vm/memory/metaspace.hpp @@ -117,9 +117,12 @@ class Metaspace : public CHeapObj { // Aligned size of the metaspace. static size_t _compressed_class_space_size; + public: static size_t compressed_class_space_size() { return _compressed_class_space_size; } + + private: static void set_compressed_class_space_size(size_t size) { _compressed_class_space_size = size; } diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 6d442111a55..98805be9ced 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -229,7 +229,8 @@ diagnostic(bool, UnrollLimitCheck, true, \ "Additional overflow checks during loop unroll") \ \ - product(bool, OptimizeFill, true, \ + /* OptimizeFill not yet supported on PowerPC. */ \ + product(bool, OptimizeFill, true PPC64_ONLY(&& false), \ "convert fill/copy loops into intrinsic") \ \ develop(bool, TraceOptimizeFill, false, \ diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 492bf384f2f..a64691fb13a 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -761,7 +761,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // processes as vector in RA. if (RegMask::is_vector(ireg)) lrg._is_vector = 1; - assert(n_type->isa_vect() == NULL || lrg._is_vector || ireg == Op_RegD, + assert(n_type->isa_vect() == NULL || lrg._is_vector || ireg == Op_RegD || ireg == Op_RegL, "vector must be in vector registers"); // Check for bound register masks @@ -961,7 +961,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { int kreg = n->in(k)->ideal_reg(); bool is_vect = RegMask::is_vector(kreg); assert(n->in(k)->bottom_type()->isa_vect() == NULL || - is_vect || kreg == Op_RegD, + is_vect || kreg == Op_RegD || kreg == Op_RegL, "vector must be in vector registers"); if (lrgmask.is_bound(kreg)) lrg._is_bound = 1; diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 7411e183cee..985dbfcc93a 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -397,6 +397,17 @@ int MachNode::operand_index( uint operand ) const { return skipped; } +int MachNode::operand_index(const MachOper *oper) const { + uint skipped = oper_input_base(); // Sum of leaves skipped so far + uint opcnt; + for (opcnt = 1; opcnt < num_opnds(); opcnt++) { + if (_opnds[opcnt] == oper) break; + uint num_edges = _opnds[opcnt]->num_edges(); // leaves for operand + skipped += num_edges; + } + if (_opnds[opcnt] != oper) return -1; + return skipped; +} //------------------------------peephole--------------------------------------- // Apply peephole rule(s) to this instruction diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index d5430194af6..213087247ff 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -31,6 +31,7 @@ #include "opto/node.hpp" #include "opto/regmask.hpp" +class BiasedLockingCounters; class BufferBlob; class CodeBuffer; class JVMState; @@ -206,6 +207,7 @@ public: // First index in _in[] corresponding to operand, or -1 if there is none int operand_index(uint operand) const; + int operand_index(const MachOper *oper) const; // Register class input is expected in virtual const RegMask &in_RegMask(uint) const; diff --git a/hotspot/src/share/vm/opto/regalloc.cpp b/hotspot/src/share/vm/opto/regalloc.cpp index 7ac02165662..8b7b1a3f091 100644 --- a/hotspot/src/share/vm/opto/regalloc.cpp +++ b/hotspot/src/share/vm/opto/regalloc.cpp @@ -77,7 +77,9 @@ int PhaseRegAlloc::reg2offset( OptoReg::Name reg ) const { assert( reg < _matcher._old_SP || (reg >= OptoReg::add(_matcher._old_SP,C->out_preserve_stack_slots()) && reg < _matcher._in_arg_limit) || - reg >= OptoReg::add(_matcher._new_SP,C->out_preserve_stack_slots()), + reg >= OptoReg::add(_matcher._new_SP, C->out_preserve_stack_slots()) || + // Allow return_addr in the out-preserve area. + reg == _matcher.return_addr(), "register allocated in a preserve area" ); return reg2offset_unchecked( reg ); } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 3f628195f78..de66a815333 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -61,17 +61,22 @@ Type::TypeInfo Type::_type_info[Type::lastype] = { { Bad, T_ILLEGAL, "tuple:", false, Node::NotAMachineReg, relocInfo::none }, // Tuple { Bad, T_ARRAY, "array:", false, Node::NotAMachineReg, relocInfo::none }, // Array -#ifndef SPARC - { Bad, T_ILLEGAL, "vectors:", false, Op_VecS, relocInfo::none }, // VectorS - { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD - { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX - { Bad, T_ILLEGAL, "vectory:", false, Op_VecY, relocInfo::none }, // VectorY -#else +#ifdef SPARC { Bad, T_ILLEGAL, "vectors:", false, 0, relocInfo::none }, // VectorS { Bad, T_ILLEGAL, "vectord:", false, Op_RegD, relocInfo::none }, // VectorD { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY -#endif // IA32 || AMD64 +#elif defined(PPC64) + { Bad, T_ILLEGAL, "vectors:", false, 0, relocInfo::none }, // VectorS + { Bad, T_ILLEGAL, "vectord:", false, Op_RegL, relocInfo::none }, // VectorD + { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX + { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY +#else // all other + { Bad, T_ILLEGAL, "vectors:", false, Op_VecS, relocInfo::none }, // VectorS + { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD + { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX + { Bad, T_ILLEGAL, "vectory:", false, Op_VecY, relocInfo::none }, // VectorY +#endif { Bad, T_ADDRESS, "anyptr:", false, Op_RegP, relocInfo::none }, // AnyPtr { Bad, T_ADDRESS, "rawptr:", false, Op_RegP, relocInfo::none }, // RawPtr { Bad, T_OBJECT, "oop:", true, Op_RegP, relocInfo::oop_type }, // OopPtr @@ -2035,6 +2040,7 @@ const TypeVect* TypeVect::make(const Type *elem, uint length) { switch (Matcher::vector_ideal_reg(size)) { case Op_VecS: return (TypeVect*)(new TypeVectS(elem, length))->hashcons(); + case Op_RegL: case Op_VecD: case Op_RegD: return (TypeVect*)(new TypeVectD(elem, length))->hashcons(); diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 9810edfe724..9aca898869c 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -524,6 +524,9 @@ public: bool is_con(int i) const { return is_con() && _lo == i; } jlong get_con() const { assert( is_con(), "" ); return _lo; } + // Check for positive 32-bit value. + int is_positive_int() const { return _lo >= 0 && _hi <= (jlong)max_jint; } + virtual bool is_finite() const; // Has a finite value virtual const Type *xmeet( const Type *t ) const; From b4ded0bc2e185e9587d1c684bab0659ce23b8dac Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 22 Nov 2013 12:14:09 -0800 Subject: [PATCH 039/265] 8029025: PPC64 (part 203): opto: Move static _in_dump_cnt to Compile object Also introduces the compiler oracle 'option' feature for PrintAssembly. Reviewed-by: kvn --- hotspot/src/share/vm/code/nmethod.cpp | 2 +- hotspot/src/share/vm/opto/callnode.cpp | 4 ++-- hotspot/src/share/vm/opto/compile.cpp | 2 ++ hotspot/src/share/vm/opto/compile.hpp | 1 + hotspot/src/share/vm/opto/idealGraphPrinter.cpp | 4 ++-- hotspot/src/share/vm/opto/node.cpp | 7 +++---- hotspot/src/share/vm/opto/node.hpp | 3 +-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 68718499a00..3cf1f8ff80d 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -619,7 +619,7 @@ nmethod* nmethod::new_nmethod(methodHandle method, InstanceKlass::cast(klass)->add_dependent_nmethod(nm); } NOT_PRODUCT(nmethod_stats.note_nmethod(nm)); - if (PrintAssembly) { + if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) { Disassembler::decode(nm); } } diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 594b650decb..12dcf38b0f2 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -342,7 +342,7 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c st->print(" %s%d]=#"INT32_FORMAT,msg,i,t->is_int()->get_con()); break; case Type::AnyPtr: - assert( t == TypePtr::NULL_PTR, "" ); + assert( t == TypePtr::NULL_PTR || n->in_dump(), "" ); st->print(" %s%d]=#NULL",msg,i); break; case Type::AryPtr: @@ -887,7 +887,7 @@ int CallStaticJavaNode::extract_uncommon_trap_request(const Node* call) { if (!(call->req() > TypeFunc::Parms && call->in(TypeFunc::Parms) != NULL && call->in(TypeFunc::Parms)->is_Con())) { - assert(_in_dump_cnt != 0, "OK if dumping"); + assert(in_dump() != 0, "OK if dumping"); tty->print("[bad uncommon trap]"); return 0; } diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index fbc7c4a21db..069e8d7646b 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -647,6 +647,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _dead_node_count(0), #ifndef PRODUCT _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), + _in_dump_cnt(0), _printer(IdealGraphPrinter::printer()), #endif _congraph(NULL), @@ -936,6 +937,7 @@ Compile::Compile( ciEnv* ci_env, _inner_loops(0), #ifndef PRODUCT _trace_opto_output(TraceOptoOutput), + _in_dump_cnt(0), _printer(NULL), #endif _dead_node_list(comp_arena()), diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 5ad53e5d163..96b847179d5 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -591,6 +591,7 @@ class Compile : public Phase { bool trace_opto_output() const { return _trace_opto_output; } bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; } void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; } + int _in_dump_cnt; // Required for dumping ir nodes. #endif // JSR 292 diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 4589f6e4a8d..851b70d3f8f 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -404,7 +404,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { Node *node = n; #ifndef PRODUCT - node->_in_dump_cnt++; + Compile::current()->_in_dump_cnt++; print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); const Type *t = node->bottom_type(); print_prop("type", t->msg()); @@ -623,7 +623,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { print_prop("lrg", lrg_id); } - node->_in_dump_cnt--; + Compile::current()->_in_dump_cnt--; #endif tail(PROPERTIES_ELEMENT); diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 1df5eb51a8c..0e0b8a0c518 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -1523,7 +1523,6 @@ Node* Node::find_ctrl(int idx) const { #ifndef PRODUCT -int Node::_in_dump_cnt = 0; // -----------------------------Name------------------------------------------- extern const char *NodeClassNames[]; @@ -1595,7 +1594,7 @@ void Node::set_debug_orig(Node* orig) { void Node::dump(const char* suffix, outputStream *st) const { Compile* C = Compile::current(); bool is_new = C->node_arena()->contains(this); - _in_dump_cnt++; + C->_in_dump_cnt++; st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name()); // Dump the required and precedence inputs @@ -1610,7 +1609,7 @@ void Node::dump(const char* suffix, outputStream *st) const { dump_orig(debug_orig(), st); #endif st->cr(); - _in_dump_cnt--; + C->_in_dump_cnt--; return; // don't process dead nodes } @@ -1662,7 +1661,7 @@ void Node::dump(const char* suffix, outputStream *st) const { } } if (suffix) st->print(suffix); - _in_dump_cnt--; + C->_in_dump_cnt--; } //------------------------------dump_req-------------------------------------- diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index d380a35f0db..b04a0fad78e 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -1033,8 +1033,7 @@ public: // RegMask Print Functions void dump_in_regmask(int idx) { in_RegMask(idx).dump(); } void dump_out_regmask() { out_RegMask().dump(); } - static int _in_dump_cnt; - static bool in_dump() { return _in_dump_cnt > 0; } + static bool in_dump() { return Compile::current()->_in_dump_cnt > 0; } void fast_dump() const { tty->print("%4d: %-17s", _idx, Name()); for (uint i = 0; i < len(); i++) From fe897661849750c3f034f3922565e30b0073281e Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Tue, 26 Nov 2013 18:38:19 -0800 Subject: [PATCH 040/265] 8028515: PPPC64 (part 113.2): opto: Introduce LoadFence/StoreFence Use new nodes for loadFence/storeFence intrinsics in C2. Reviewed-by: kvn, dholmes --- hotspot/make/jprt.properties | 72 ++++++++++++++++++++++ hotspot/src/cpu/sparc/vm/sparc.ad | 2 + hotspot/src/cpu/x86/vm/x86_32.ad | 2 + hotspot/src/cpu/x86/vm/x86_64.ad | 2 + hotspot/src/share/vm/adlc/formssel.cpp | 14 +++-- hotspot/src/share/vm/opto/classes.hpp | 2 + hotspot/src/share/vm/opto/library_call.cpp | 4 +- hotspot/src/share/vm/opto/matcher.cpp | 4 +- hotspot/src/share/vm/opto/memnode.cpp | 30 +++++---- hotspot/src/share/vm/opto/memnode.hpp | 22 +++++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 2 + 11 files changed, 135 insertions(+), 21 deletions(-) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 9109ded6f98..a0548f2b37f 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -329,9 +329,81 @@ jprt.my.linux.i586.test.targets.embedded = \ # The complete list of test targets for jprt # Note: no PPC or ARM tests at this stage +jprt.my.linux.armvfpsflt.test.targets.embedded = \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_default, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_CMS, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_G1, \ + linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ + linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC + +# QEMU Emulators for ARM VFP HFLT +jprt.my.linux.armvfphflt.test.targets.embedded = \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_default, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_CMS, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_G1, \ + linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ + linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC + +jprt.my.linux.ppc.test.targets.embedded = \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_default, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_CMS, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_G1, \ + linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ + linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC jprt.test.targets.standard = \ ${jprt.my.linux.i586.test.targets.embedded}, \ + ${jprt.my.linux.armvfpsflt.test.targets.embedded}, \ + ${jprt.my.linux.armvfphflt.test.targets.embedded}, \ + ${jprt.my.linux.ppc.test.targets.embedded}, \ ${jprt.my.solaris.sparcv9.test.targets}, \ ${jprt.my.solaris.x64.test.targets}, \ ${jprt.my.linux.i586.test.targets}, \ diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index a84af2e8ee8..8dfe76b5a23 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -6651,6 +6651,7 @@ instruct decodeKlass_not_null(iRegP dst, iRegN src) %{ instruct membar_acquire() %{ match(MemBarAcquire); + match(LoadFence); ins_cost(4*MEMORY_REF_COST); size(0); @@ -6671,6 +6672,7 @@ instruct membar_acquire_lock() %{ instruct membar_release() %{ match(MemBarRelease); + match(StoreFence); ins_cost(4*MEMORY_REF_COST); size(0); diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 00a9861df89..e9d34e948cf 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -7096,6 +7096,7 @@ instruct storeSSL(stackSlotL dst, eRegL src) %{ instruct membar_acquire() %{ match(MemBarAcquire); + match(LoadFence); ins_cost(400); size(0); @@ -7116,6 +7117,7 @@ instruct membar_acquire_lock() %{ instruct membar_release() %{ match(MemBarRelease); + match(StoreFence); ins_cost(400); size(0); diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index b94f5a5422c..12280ddb157 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -6345,6 +6345,7 @@ instruct popCountL_mem(rRegI dst, memory mem, rFlagsReg cr) %{ instruct membar_acquire() %{ match(MemBarAcquire); + match(LoadFence); ins_cost(0); size(0); @@ -6367,6 +6368,7 @@ instruct membar_acquire_lock() instruct membar_release() %{ match(MemBarRelease); + match(StoreFence); ins_cost(0); size(0); diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index b20835815e3..904b888c2bc 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -648,6 +648,8 @@ bool InstructForm::is_wide_memory_kill(FormDict &globals) const { if( strcmp(_matrule->_opType,"MemBarReleaseLock") == 0 ) return true; if( strcmp(_matrule->_opType,"MemBarAcquireLock") == 0 ) return true; if( strcmp(_matrule->_opType,"MemBarStoreStore") == 0 ) return true; + if( strcmp(_matrule->_opType,"StoreFence") == 0 ) return true; + if( strcmp(_matrule->_opType,"LoadFence") == 0 ) return true; return false; } @@ -4054,13 +4056,15 @@ bool MatchRule::is_ideal_fastlock() const { bool MatchRule::is_ideal_membar() const { if( !_opType ) return false; return - !strcmp(_opType,"MemBarAcquire" ) || - !strcmp(_opType,"MemBarRelease" ) || + !strcmp(_opType,"MemBarAcquire") || + !strcmp(_opType,"MemBarRelease") || !strcmp(_opType,"MemBarAcquireLock") || !strcmp(_opType,"MemBarReleaseLock") || - !strcmp(_opType,"MemBarVolatile" ) || - !strcmp(_opType,"MemBarCPUOrder" ) || - !strcmp(_opType,"MemBarStoreStore" ); + !strcmp(_opType,"LoadFence" ) || + !strcmp(_opType,"StoreFence") || + !strcmp(_opType,"MemBarVolatile") || + !strcmp(_opType,"MemBarCPUOrder") || + !strcmp(_opType,"MemBarStoreStore"); } bool MatchRule::is_ideal_loadPC() const { diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 002d2db636d..79aa1b8b628 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -175,9 +175,11 @@ macro(MathExactI) macro(MathExactL) macro(MaxI) macro(MemBarAcquire) +macro(LoadFence) macro(MemBarAcquireLock) macro(MemBarCPUOrder) macro(MemBarRelease) +macro(StoreFence) macro(MemBarReleaseLock) macro(MemBarVolatile) macro(MemBarStoreStore) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 14f7015bd03..8ad2fb7cff4 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -3105,10 +3105,10 @@ bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) { insert_mem_bar(Op_MemBarCPUOrder); switch(id) { case vmIntrinsics::_loadFence: - insert_mem_bar(Op_MemBarAcquire); + insert_mem_bar(Op_LoadFence); return true; case vmIntrinsics::_storeFence: - insert_mem_bar(Op_MemBarRelease); + insert_mem_bar(Op_StoreFence); return true; case vmIntrinsics::_fullFence: insert_mem_bar(Op_MemBarVolatile); diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 87eb2244697..708711e2a64 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -2333,7 +2333,7 @@ void Matcher::validate_null_checks( ) { bool Matcher::post_store_load_barrier(const Node* vmb) { Compile* C = Compile::current(); assert(vmb->is_MemBar(), ""); - assert(vmb->Opcode() != Op_MemBarAcquire, ""); + assert(vmb->Opcode() != Op_MemBarAcquire && vmb->Opcode() != Op_LoadFence, ""); const MemBarNode* membar = vmb->as_MemBar(); // Get the Ideal Proj node, ctrl, that can be used to iterate forward @@ -2378,7 +2378,7 @@ bool Matcher::post_store_load_barrier(const Node* vmb) { if (x->is_MemBar()) { // We must retain this membar if there is an upcoming volatile // load, which will be followed by acquire membar. - if (xop == Op_MemBarAcquire) { + if (xop == Op_MemBarAcquire || xop == Op_LoadFence) { return false; } else { // For other kinds of barriers, check by pretending we diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index db956862482..939827b89b8 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1002,9 +1002,13 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { // a synchronized region. while (current->is_Proj()) { int opc = current->in(0)->Opcode(); - if ((final && (opc == Op_MemBarAcquire || opc == Op_MemBarAcquireLock)) || - opc == Op_MemBarRelease || opc == Op_MemBarCPUOrder || - opc == Op_MemBarReleaseLock) { + if ((final && (opc == Op_MemBarAcquire || + opc == Op_MemBarAcquireLock || + opc == Op_LoadFence)) || + opc == Op_MemBarRelease || + opc == Op_StoreFence || + opc == Op_MemBarReleaseLock || + opc == Op_MemBarCPUOrder) { Node* mem = current->in(0)->in(TypeFunc::Memory); if (mem->is_MergeMem()) { MergeMemNode* merge = mem->as_MergeMem(); @@ -2973,15 +2977,17 @@ uint MemBarNode::cmp( const Node &n ) const { //------------------------------make------------------------------------------- MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { switch (opcode) { - case Op_MemBarAcquire: return new(C) MemBarAcquireNode(C, atp, pn); - case Op_MemBarRelease: return new(C) MemBarReleaseNode(C, atp, pn); - case Op_MemBarAcquireLock: return new(C) MemBarAcquireLockNode(C, atp, pn); - case Op_MemBarReleaseLock: return new(C) MemBarReleaseLockNode(C, atp, pn); - case Op_MemBarVolatile: return new(C) MemBarVolatileNode(C, atp, pn); - case Op_MemBarCPUOrder: return new(C) MemBarCPUOrderNode(C, atp, pn); - case Op_Initialize: return new(C) InitializeNode(C, atp, pn); - case Op_MemBarStoreStore: return new(C) MemBarStoreStoreNode(C, atp, pn); - default: ShouldNotReachHere(); return NULL; + case Op_MemBarAcquire: return new(C) MemBarAcquireNode(C, atp, pn); + case Op_LoadFence: return new(C) LoadFenceNode(C, atp, pn); + case Op_MemBarRelease: return new(C) MemBarReleaseNode(C, atp, pn); + case Op_StoreFence: return new(C) StoreFenceNode(C, atp, pn); + case Op_MemBarAcquireLock: return new(C) MemBarAcquireLockNode(C, atp, pn); + case Op_MemBarReleaseLock: return new(C) MemBarReleaseLockNode(C, atp, pn); + case Op_MemBarVolatile: return new(C) MemBarVolatileNode(C, atp, pn); + case Op_MemBarCPUOrder: return new(C) MemBarCPUOrderNode(C, atp, pn); + case Op_Initialize: return new(C) InitializeNode(C, atp, pn); + case Op_MemBarStoreStore: return new(C) MemBarStoreStoreNode(C, atp, pn); + default: ShouldNotReachHere(); return NULL; } } diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 750a79af8a2..7c92e1c5a7c 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -994,6 +994,17 @@ public: virtual int Opcode() const; }; +// "Acquire" - no following ref can move before (but earlier refs can +// follow, like an early Load stalled in cache). Requires multi-cpu +// visibility. Inserted independ of any load, as required +// for intrinsic sun.misc.Unsafe.loadFence(). +class LoadFenceNode: public MemBarNode { +public: + LoadFenceNode(Compile* C, int alias_idx, Node* precedent) + : MemBarNode(C, alias_idx, precedent) {} + virtual int Opcode() const; +}; + // "Release" - no earlier ref can move after (but later refs can move // up, like a speculative pipelined cache-hitting Load). Requires // multi-cpu visibility. Inserted before a volatile store. @@ -1004,6 +1015,17 @@ public: virtual int Opcode() const; }; +// "Release" - no earlier ref can move after (but later refs can move +// up, like a speculative pipelined cache-hitting Load). Requires +// multi-cpu visibility. Inserted independent of any store, as required +// for intrinsic sun.misc.Unsafe.storeFence(). +class StoreFenceNode: public MemBarNode { +public: + StoreFenceNode(Compile* C, int alias_idx, Node* precedent) + : MemBarNode(C, alias_idx, precedent) {} + virtual int Opcode() const; +}; + // "Acquire" - no following ref can move before (but earlier refs can // follow, like an early Load stalled in cache). Requires multi-cpu // visibility. Inserted after a FastLock. diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 1867ba51324..b67187c6e3d 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1820,6 +1820,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_c2_type(MemBarNode, MultiNode) \ declare_c2_type(MemBarAcquireNode, MemBarNode) \ declare_c2_type(MemBarReleaseNode, MemBarNode) \ + declare_c2_type(LoadFenceNode, MemBarNode) \ + declare_c2_type(StoreFenceNode, MemBarNode) \ declare_c2_type(MemBarVolatileNode, MemBarNode) \ declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ declare_c2_type(InitializeNode, MemBarNode) \ From ecca1bcc72e9fb51fd905d7f8b10147ed93012f0 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 27 Nov 2013 16:16:21 -0800 Subject: [PATCH 041/265] 8029015: PPC64 (part 216): opto: trap based null and range checks On PPC64 use tdi instruction that does a compare and raises SIGTRAP for NULL and range checks. Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 7 +- hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 2 + hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 7 +- hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp | 2 + hotspot/src/cpu/sparc/vm/globals_sparc.hpp | 3 +- hotspot/src/cpu/x86/vm/c2_globals_x86.hpp | 2 + hotspot/src/cpu/x86/vm/globals_x86.hpp | 3 +- hotspot/src/cpu/zero/vm/globals_zero.hpp | 1 + hotspot/src/share/vm/adlc/main.cpp | 1 + hotspot/src/share/vm/adlc/output_h.cpp | 16 ++- hotspot/src/share/vm/opto/block.cpp | 124 ++++++++++++++---- hotspot/src/share/vm/opto/block.hpp | 1 + hotspot/src/share/vm/opto/c2_globals.hpp | 6 +- hotspot/src/share/vm/opto/compile.cpp | 20 ++- hotspot/src/share/vm/opto/compile.hpp | 5 + hotspot/src/share/vm/opto/gcm.cpp | 11 +- hotspot/src/share/vm/opto/machnode.hpp | 3 + hotspot/src/share/vm/opto/matcher.cpp | 63 +++++++++ hotspot/src/share/vm/opto/matcher.hpp | 2 + hotspot/src/share/vm/opto/output.cpp | 12 ++ hotspot/src/share/vm/runtime/globals.hpp | 6 + 21 files changed, 244 insertions(+), 53 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index b39151004c9..1e3c327765f 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -38,6 +38,7 @@ define_pd_global(bool, NeedsDeoptSuspend, false); // Only register window ma define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks. +define_pd_global(bool, TrapBasedNullChecks, true); define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast. // Use large code-entry alignment. @@ -100,12 +101,6 @@ define_pd_global(uintx, TypeProfileLevel, 0); product(bool, TrapBasedNotEntrantChecks, true, \ "Raise and handle SIGTRAP if calling not entrant or zombie" \ " method.") \ - product(bool, TrapBasedNullChecks, true, \ - "Generate code for null checks that uses a cmp and trap " \ - "instruction raising SIGTRAP. This is only used if an access to" \ - "null (+offset) will not raise a SIGSEGV.") \ - product(bool, TrapBasedRangeChecks, true, \ - "Raise and handle SIGTRAP if array out of bounds check fails.") \ product(bool, TraceTraps, false, "Trace all traps the signal handler" \ "handles.") \ \ diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index b70a859bf30..c2ff51183c1 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -76,11 +76,13 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { } static bool is_sigill_zombie_not_entrant_at(address addr); +#ifdef COMPILER2 // SIGTRAP-based implicit range checks bool is_sigtrap_range_check() { assert(UseSIGTRAP && TrapBasedRangeChecks, "precondition"); return MacroAssembler::is_trap_range_check(long_at(0)); } +#endif // 'should not reach here'. bool is_sigtrap_should_not_reach_here() { diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 079b781d655..de2af7c34b6 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -77,14 +77,17 @@ void VM_Version::initialize() { MSG(TrapBasedICMissChecks); MSG(TrapBasedNotEntrantChecks); MSG(TrapBasedNullChecks); - MSG(TrapBasedRangeChecks); FLAG_SET_ERGO(bool, TrapBasedNotEntrantChecks, false); FLAG_SET_ERGO(bool, TrapBasedNullChecks, false); FLAG_SET_ERGO(bool, TrapBasedICMissChecks, false); - FLAG_SET_ERGO(bool, TrapBasedRangeChecks, false); } #ifdef COMPILER2 + if (!UseSIGTRAP) { + MSG(TrapBasedRangeChecks); + FLAG_SET_ERGO(bool, TrapBasedRangeChecks, false); + } + // On Power6 test for section size. if (PowerArchitecturePPC64 == 6) determine_section_size(); diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index e4fe6bb00a4..32747c798c4 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -90,6 +90,8 @@ define_pd_global(uint64_t,MaxRAM, 4ULL*G); define_pd_global(uintx, CodeCacheMinBlockLength, 4); define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed on sparc. + // Heap related flags define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index ecc6eb61524..8dd047927a1 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -43,7 +43,8 @@ define_pd_global(bool, CountInterpCalls, false); // not implemented i define_pd_global(bool, NeedsDeoptSuspend, true); // register window machines need this define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks -define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast +define_pd_global(bool, TrapBasedNullChecks, false); // Not needed on sparc. +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast define_pd_global(intx, CodeEntryAlignment, 32); // The default setting 16/16 seems to work best. diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index a45bd9624e5..6ca78039c8b 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -88,6 +88,8 @@ define_pd_global(intx, ReservedCodeCacheSize, 48*M); define_pd_global(uintx, CodeCacheMinBlockLength, 4); define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed on x86. + // Heap related flags define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index b194ffbcfbe..e82c192901b 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -37,7 +37,8 @@ define_pd_global(bool, CountInterpCalls, true); define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks -define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast +define_pd_global(bool, TrapBasedNullChecks, false); // Not needed on x86. +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast // See 4827828 for this change. There is no globals_core_i486.hpp. I can't // assign a different value for C2 without touching a number of files. Use diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index 67fcfba5720..993064536bb 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -38,6 +38,7 @@ define_pd_global(bool, CountInterpCalls, true); define_pd_global(bool, NeedsDeoptSuspend, false); define_pd_global(bool, ImplicitNullChecks, true); +define_pd_global(bool, TrapBasedNullChecks, false); define_pd_global(bool, UncommonNullCast, true); define_pd_global(intx, CodeEntryAlignment, 32); diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index 2b61bdbeb73..612d0e582d9 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.cpp @@ -272,6 +272,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_PIPELINE_file, "adfiles", get_basename(AD._HPP_file._name)); AD.addInclude(AD._DFA_file, "precompiled.hpp"); AD.addInclude(AD._DFA_file, "adfiles", get_basename(AD._HPP_file._name)); + AD.addInclude(AD._DFA_file, "opto/cfgnode.hpp"); // Use PROB_MAX in predicate. AD.addInclude(AD._DFA_file, "opto/matcher.hpp"); AD.addInclude(AD._DFA_file, "opto/opcodes.hpp"); // Make sure each .cpp file starts with include lines: diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 34a3ba9681a..fa9b79a172a 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1615,15 +1615,19 @@ void ArchDesc::declareClasses(FILE *fp) { Attribute *attr = instr->_attribs; bool avoid_back_to_back = false; while (attr != NULL) { - if (strcmp (attr->_ident,"ins_cost") && - strncmp(attr->_ident,"ins_field_", 10) != 0 && - strcmp (attr->_ident,"ins_short_branch")) { - fprintf(fp," virtual int %s() const { return %s; }\n", - attr->_ident, attr->_val); + if (strcmp (attr->_ident, "ins_cost") != 0 && + strncmp(attr->_ident, "ins_field_", 10) != 0 && + // Must match function in node.hpp: return type bool, no prefix "ins_". + strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") != 0 && + strcmp (attr->_ident, "ins_short_branch") != 0) { + fprintf(fp, " virtual int %s() const { return %s; }\n", attr->_ident, attr->_val); } // Check value for ins_avoid_back_to_back, and if it is true (1), set the flag - if (!strcmp(attr->_ident,"ins_avoid_back_to_back") && attr->int_val(*this) != 0) + if (!strcmp(attr->_ident, "ins_avoid_back_to_back") != 0 && attr->int_val(*this) != 0) avoid_back_to_back = true; + if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) + fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val); + attr = (Attribute *)attr->_next; } diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 4b7fc6409ce..9d2f9522bed 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -530,18 +530,27 @@ void PhaseCFG::insert_goto_at(uint block_no, uint succ_no) { // Does this block end in a multiway branch that cannot have the default case // flipped for another case? -static bool no_flip_branch( Block *b ) { +static bool no_flip_branch(Block *b) { int branch_idx = b->number_of_nodes() - b->_num_succs-1; - if( branch_idx < 1 ) return false; - Node *bra = b->get_node(branch_idx); - if( bra->is_Catch() ) + if (branch_idx < 1) { + return false; + } + Node *branch = b->get_node(branch_idx); + if (branch->is_Catch()) { return true; - if( bra->is_Mach() ) { - if( bra->is_MachNullCheck() ) + } + if (branch->is_Mach()) { + if (branch->is_MachNullCheck()) { return true; - int iop = bra->as_Mach()->ideal_Opcode(); - if( iop == Op_FastLock || iop == Op_FastUnlock ) + } + int iop = branch->as_Mach()->ideal_Opcode(); + if (iop == Op_FastLock || iop == Op_FastUnlock) { return true; + } + // Don't flip if branch has an implicit check. + if (branch->as_Mach()->is_TrapBasedCheckNode()) { + return true; + } } return false; } @@ -700,6 +709,57 @@ void PhaseCFG::remove_empty_blocks() { } // End of for all blocks } +Block *PhaseCFG::fixup_trap_based_check(Node *branch, Block *block, int block_pos, Block *bnext) { + // Trap based checks must fall through to the successor with + // PROB_ALWAYS. + // They should be an If with 2 successors. + assert(branch->is_MachIf(), "must be If"); + assert(block->_num_succs == 2, "must have 2 successors"); + + // Get the If node and the projection for the first successor. + MachIfNode *iff = block->get_node(block->number_of_nodes()-3)->as_MachIf(); + ProjNode *proj0 = block->get_node(block->number_of_nodes()-2)->as_Proj(); + ProjNode *proj1 = block->get_node(block->number_of_nodes()-1)->as_Proj(); + ProjNode *projt = (proj0->Opcode() == Op_IfTrue) ? proj0 : proj1; + ProjNode *projf = (proj0->Opcode() == Op_IfFalse) ? proj0 : proj1; + + // Assert that proj0 and succs[0] match up. Similarly for proj1 and succs[1]. + assert(proj0->raw_out(0) == block->_succs[0]->head(), "Mismatch successor 0"); + assert(proj1->raw_out(0) == block->_succs[1]->head(), "Mismatch successor 1"); + + ProjNode *proj_always; + ProjNode *proj_never; + // We must negate the branch if the implicit check doesn't follow + // the branch's TRUE path. Then, the new TRUE branch target will + // be the old FALSE branch target. + if (iff->_prob <= 2*PROB_NEVER) { // There are small rounding errors. + proj_never = projt; + proj_always = projf; + } else { + // We must negate the branch if the trap doesn't follow the + // branch's TRUE path. Then, the new TRUE branch target will + // be the old FALSE branch target. + proj_never = projf; + proj_always = projt; + iff->negate(); + } + assert(iff->_prob <= 2*PROB_NEVER, "Trap based checks are expected to trap never!"); + // Map the successors properly + block->_succs.map(0, get_block_for_node(proj_never ->raw_out(0))); // The target of the trap. + block->_succs.map(1, get_block_for_node(proj_always->raw_out(0))); // The fall through target. + + // Place the fall through block after this block. + Block *bs1 = block->non_connector_successor(1); + if (bs1 != bnext && move_to_next(bs1, block_pos)) { + bnext = bs1; + } + // If the fall through block still is not the next block, insert a goto. + if (bs1 != bnext) { + insert_goto_at(block_pos, 1); + } + return bnext; +} + // Fix up the final control flow for basic blocks. void PhaseCFG::fixup_flow() { // Fixup final control flow for the blocks. Remove jump-to-next @@ -723,25 +783,39 @@ void PhaseCFG::fixup_flow() { // Check for multi-way branches where I cannot negate the test to // exchange the true and false targets. if (no_flip_branch(block)) { - // Find fall through case - if must fall into its target + // Find fall through case - if must fall into its target. + // Get the index of the branch's first successor. int branch_idx = block->number_of_nodes() - block->_num_succs; - for (uint j2 = 0; j2 < block->_num_succs; j2++) { - const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); - if (p->_con == 0) { - // successor j2 is fall through case - if (block->non_connector_successor(j2) != bnext) { - // but it is not the next block => insert a goto - insert_goto_at(i, j2); + + // The branch is 1 before the branch's first successor. + Node *branch = block->get_node(branch_idx-1); + + // Handle no-flip branches which have implicit checks and which require + // special block ordering and individual semantics of the 'fall through + // case'. + if ((TrapBasedNullChecks || TrapBasedRangeChecks) && + branch->is_Mach() && branch->as_Mach()->is_TrapBasedCheckNode()) { + bnext = fixup_trap_based_check(branch, block, i, bnext); + } else { + // Else, default handling for no-flip branches + for (uint j2 = 0; j2 < block->_num_succs; j2++) { + const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); + if (p->_con == 0) { + // successor j2 is fall through case + if (block->non_connector_successor(j2) != bnext) { + // but it is not the next block => insert a goto + insert_goto_at(i, j2); + } + // Put taken branch in slot 0 + if (j2 == 0 && block->_num_succs == 2) { + // Flip targets in succs map + Block *tbs0 = block->_succs[0]; + Block *tbs1 = block->_succs[1]; + block->_succs.map(0, tbs1); + block->_succs.map(1, tbs0); + } + break; } - // Put taken branch in slot 0 - if (j2 == 0 && block->_num_succs == 2) { - // Flip targets in succs map - Block *tbs0 = block->_succs[0]; - Block *tbs1 = block->_succs[1]; - block->_succs.map(0, tbs1); - block->_succs.map(1, tbs0); - } - break; } } diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index 1d6028bd5ea..76393a82100 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -590,6 +590,7 @@ class PhaseCFG : public Phase { // Remove empty basic blocks void remove_empty_blocks(); + Block *fixup_trap_based_check(Node *branch, Block *block, int block_pos, Block *bnext); void fixup_flow(); // Insert a node into a block at index and map the node to the block diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 98805be9ced..9ae827b6631 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -654,7 +654,11 @@ "Propagate type improvements in callers of inlinee if possible") \ \ experimental(bool, UseTypeSpeculation, false, \ - "Speculatively propagate types from profiles") + "Speculatively propagate types from profiles") \ + \ + product_pd(bool, TrapBasedRangeChecks, \ + "Generate code for range checks that uses a cmp and trap " \ + "instruction raising SIGTRAP. Used on PPC64.") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 069e8d7646b..8b3c21555b8 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -860,6 +860,10 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr int next_slot = _orig_pc_slot + (sizeof(address) / VMRegImpl::stack_slot_size); set_fixed_slots(next_slot); + // Compute when to use implicit null checks. Used by matching trap based + // nodes and NullCheck optimization. + set_allowed_deopt_reasons(); + // Now generate code Code_Gen(); if (failing()) return; @@ -948,7 +952,8 @@ Compile::Compile( ciEnv* ci_env, _inlining_incrementally(false), _print_inlining_list(NULL), _print_inlining_idx(0), - _preserve_jvm_state(0) { + _preserve_jvm_state(0), + _allowed_reasons(0) { C = this; #ifndef PRODUCT @@ -3350,6 +3355,19 @@ bool Compile::too_many_recompiles(ciMethod* method, } } +// Compute when not to trap. Used by matching trap based nodes and +// NullCheck optimization. +void Compile::set_allowed_deopt_reasons() { + _allowed_reasons = 0; + if (is_method_compilation()) { + for (int rs = (int)Deoptimization::Reason_none+1; rs < Compile::trapHistLength; rs++) { + assert(rs < BitsPerInt, "recode bit map"); + if (!too_many_traps((Deoptimization::DeoptReason) rs)) { + _allowed_reasons |= nth_bit(rs); + } + } + } +} #ifndef PRODUCT //------------------------------verify_graph_edges--------------------------- diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 96b847179d5..acc2f1c6cad 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -855,6 +855,11 @@ class Compile : public Phase { ciMethodData* logmd = NULL); // Report if there were too many recompiles at a method and bci. bool too_many_recompiles(ciMethod* method, int bci, Deoptimization::DeoptReason reason); + // Return a bitset with the reasons where deoptimization is allowed, + // i.e., where there were not too many uncommon traps. + int _allowed_reasons; + int allowed_deopt_reasons() { return _allowed_reasons; } + void set_allowed_deopt_reasons(); // Parsing, optimization PhaseGVN* initial_gvn() { return _initial_gvn; } diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index 33720499471..58dac3c42de 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1330,15 +1330,6 @@ void PhaseCFG::global_code_motion() { // with suitable memory ops nearby. Use the memory op to do the NULL check. // I can generate a memory op if there is not one nearby. if (C->is_method_compilation()) { - // Don't do it for natives, adapters, or runtime stubs - int allowed_reasons = 0; - // ...and don't do it when there have been too many traps, globally. - for (int reason = (int)Deoptimization::Reason_none+1; - reason < Compile::trapHistLength; reason++) { - assert(reason < BitsPerInt, "recode bit map"); - if (!C->too_many_traps((Deoptimization::DeoptReason) reason)) - allowed_reasons |= nth_bit(reason); - } // By reversing the loop direction we get a very minor gain on mpegaudio. // Feel free to revert to a forward loop for clarity. // for( int i=0; i < (int)matcher._null_check_tests.size(); i+=2 ) { @@ -1346,7 +1337,7 @@ void PhaseCFG::global_code_motion() { Node* proj = _matcher._null_check_tests[i]; Node* val = _matcher._null_check_tests[i + 1]; Block* block = get_block_for_node(proj); - implicit_null_check(block, proj, val, allowed_reasons); + implicit_null_check(block, proj, val, C->allowed_deopt_reasons()); // The implicit_null_check will only perform the transformation // if the null branch is truly uncommon, *and* it leads to an // uncommon trap. Combined with the too_many_traps guards diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 213087247ff..35498dbd5f5 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -315,6 +315,9 @@ public: static const Pipeline *pipeline_class(); virtual const Pipeline *pipeline() const; + // Returns true if this node is a check that can be implemented with a trap. + virtual bool is_TrapBasedCheckNode() const { return false; } + #ifndef PRODUCT virtual const char *Name() const = 0; // Machine-specific name virtual void dump_spec(outputStream *st) const; // Print per-node info diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 708711e2a64..311bd249335 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -2395,6 +2395,69 @@ bool Matcher::post_store_load_barrier(const Node* vmb) { return false; } +// Check whether node n is a branch to an uncommon trap that we could +// optimize as test with very high branch costs in case of going to +// the uncommon trap. The code must be able to be recompiled to use +// a cheaper test. +bool Matcher::branches_to_uncommon_trap(const Node *n) { + // Don't do it for natives, adapters, or runtime stubs + Compile *C = Compile::current(); + if (!C->is_method_compilation()) return false; + + assert(n->is_If(), "You should only call this on if nodes."); + IfNode *ifn = n->as_If(); + + Node *ifFalse = NULL; + for (DUIterator_Fast imax, i = ifn->fast_outs(imax); i < imax; i++) { + if (ifn->fast_out(i)->is_IfFalse()) { + ifFalse = ifn->fast_out(i); + break; + } + } + assert(ifFalse, "An If should have an ifFalse. Graph is broken."); + + Node *reg = ifFalse; + int cnt = 4; // We must protect against cycles. Limit to 4 iterations. + // Alternatively use visited set? Seems too expensive. + while (reg != NULL && cnt > 0) { + CallNode *call = NULL; + RegionNode *nxt_reg = NULL; + for (DUIterator_Fast imax, i = reg->fast_outs(imax); i < imax; i++) { + Node *o = reg->fast_out(i); + if (o->is_Call()) { + call = o->as_Call(); + } + if (o->is_Region()) { + nxt_reg = o->as_Region(); + } + } + + if (call && + call->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) { + const Type* trtype = call->in(TypeFunc::Parms)->bottom_type(); + if (trtype->isa_int() && trtype->is_int()->is_con()) { + jint tr_con = trtype->is_int()->get_con(); + Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(tr_con); + Deoptimization::DeoptAction action = Deoptimization::trap_request_action(tr_con); + assert((int)reason < (int)BitsPerInt, "recode bit map"); + + if (is_set_nth_bit(C->allowed_deopt_reasons(), (int)reason) + && action != Deoptimization::Action_none) { + // This uncommon trap is sure to recompile, eventually. + // When that happens, C->too_many_traps will prevent + // this transformation from happening again. + return true; + } + } + } + + reg = nxt_reg; + cnt--; + } + + return false; +} + //============================================================================= //---------------------------State--------------------------------------------- State::State(void) { diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index 521c188a0d2..4c805f5d792 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -485,6 +485,8 @@ public: // retain the Node to act as a compiler ordering barrier. static bool post_store_load_barrier(const Node* mb); + // Does n lead to an uncommon trap that can cause deoptimization? + static bool branches_to_uncommon_trap(const Node *n); #ifdef ASSERT void dump_old2new_map(); // machine-independent to machine-dependent diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 737632a7d93..4fb8ba8879d 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1459,6 +1459,12 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { // Intel all the time, with add-to-memory kind of opcodes. previous_offset = current_offset; } + + // Not an else-if! + // If this is a trap based cmp then add its offset to the list. + if (mach->is_TrapBasedCheckNode()) { + inct_starts[inct_cnt++] = current_offset; + } } // Verify that there is sufficient space remaining @@ -1725,6 +1731,12 @@ void Compile::FillExceptionTables(uint cnt, uint *call_returns, uint *inct_start _inc_table.append(inct_starts[inct_cnt++], blk_labels[block_num].loc_pos()); continue; } + // Handle implicit exception table updates: trap instructions. + if (n->is_Mach() && n->as_Mach()->is_TrapBasedCheckNode()) { + uint block_num = block->non_connector_successor(0)->_pre_order; + _inc_table.append(inct_starts[inct_cnt++], blk_labels[block_num].loc_pos()); + continue; + } } // End of for all blocks fill in exception table entries } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 3fbbaa138d3..0b5be1fde4b 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2500,6 +2500,12 @@ class CommandLineFlags { develop_pd(bool, ImplicitNullChecks, \ "Generate code for implicit null checks") \ \ + product_pd(bool, TrapBasedNullChecks, \ + "Generate code for null checks that uses a cmp and trap " \ + "instruction raising SIGTRAP. This is only used if an access to" \ + "null (+offset) will not raise a SIGSEGV, i.e.," \ + "ImplicitNullChecks don't work (PPC64).") \ + \ product(bool, PrintSafepointStatistics, false, \ "Print statistics about safepoint synchronization") \ \ From d767bd2dfd576e4d77f652c2444ea9bcf726ef43 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Thu, 5 Dec 2013 19:19:09 +0100 Subject: [PATCH 042/265] 8019929: PPC64 (part 107): Extend ELF-decoder to support PPC64 function descriptor tables Extend ELF-decoder to support PPC64 function descriptor tables Reviewed-by: kvn, zgu --- hotspot/make/aix/makefiles/vm.make | 4 +- hotspot/src/os/linux/vm/decoder_linux.cpp | 6 + .../src/share/vm/utilities/decoder_elf.cpp | 2 +- .../src/share/vm/utilities/decoder_elf.hpp | 4 +- hotspot/src/share/vm/utilities/elfFile.cpp | 52 +++++- hotspot/src/share/vm/utilities/elfFile.hpp | 8 +- .../share/vm/utilities/elfFuncDescTable.cpp | 104 ++++++++++++ .../share/vm/utilities/elfFuncDescTable.hpp | 149 ++++++++++++++++++ .../src/share/vm/utilities/elfStringTable.cpp | 4 +- .../src/share/vm/utilities/elfStringTable.hpp | 2 +- .../src/share/vm/utilities/elfSymbolTable.cpp | 38 +++-- .../src/share/vm/utilities/elfSymbolTable.hpp | 6 +- 12 files changed, 350 insertions(+), 29 deletions(-) create mode 100644 hotspot/src/share/vm/utilities/elfFuncDescTable.cpp create mode 100644 hotspot/src/share/vm/utilities/elfFuncDescTable.hpp diff --git a/hotspot/make/aix/makefiles/vm.make b/hotspot/make/aix/makefiles/vm.make index a07b67ec772..21818dcdc1a 100644 --- a/hotspot/make/aix/makefiles/vm.make +++ b/hotspot/make/aix/makefiles/vm.make @@ -202,8 +202,8 @@ Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_ Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE)) -# Disable 155427 on aix. -Src_Files_EXCLUDE += decoder_elf.cpp elfFile.cpp elfStringTable.cpp elfSymbolTable.cpp +# Disable ELF decoder on AIX (AIX uses XCOFF). +Src_Files_EXCLUDE += decoder_elf.cpp elfFile.cpp elfStringTable.cpp elfSymbolTable.cpp elfFuncDescTable.cpp # Special handling of arch model. ifeq ($(Platform_arch_model), x86_32) diff --git a/hotspot/src/os/linux/vm/decoder_linux.cpp b/hotspot/src/os/linux/vm/decoder_linux.cpp index 915593a4e9a..0a351969d0d 100644 --- a/hotspot/src/os/linux/vm/decoder_linux.cpp +++ b/hotspot/src/os/linux/vm/decoder_linux.cpp @@ -32,6 +32,12 @@ bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { char* result; size_t size = (size_t)buflen; +#ifdef PPC64 + // On PPC64 ElfDecoder::decode() may return a dot (.) prefixed name + // (see elfFuncDescTable.hpp for details) + if (symbol && *symbol == '.') symbol += 1; +#endif + // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, // __cxa_demangle will call system "realloc" for additional memory, which // may use different malloc/realloc mechanism that allocates 'buf'. diff --git a/hotspot/src/share/vm/utilities/decoder_elf.cpp b/hotspot/src/share/vm/utilities/decoder_elf.cpp index 6e23f5eebe3..97308832139 100644 --- a/hotspot/src/share/vm/utilities/decoder_elf.cpp +++ b/hotspot/src/share/vm/utilities/decoder_elf.cpp @@ -73,4 +73,4 @@ ElfFile* ElfDecoder::get_elf_file(const char* filepath) { return file; } -#endif +#endif // !_WINDOWS && !__APPLE__ diff --git a/hotspot/src/share/vm/utilities/decoder_elf.hpp b/hotspot/src/share/vm/utilities/decoder_elf.hpp index 79652aefff1..f0d3372a9bd 100644 --- a/hotspot/src/share/vm/utilities/decoder_elf.hpp +++ b/hotspot/src/share/vm/utilities/decoder_elf.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * 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,5 +55,5 @@ private: ElfFile* _opened_elf_files; }; -#endif +#endif // !_WINDOWS && !__APPLE__ #endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP diff --git a/hotspot/src/share/vm/utilities/elfFile.cpp b/hotspot/src/share/vm/utilities/elfFile.cpp index 9fba1c39cc2..371a036406c 100644 --- a/hotspot/src/share/vm/utilities/elfFile.cpp +++ b/hotspot/src/share/vm/utilities/elfFile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * 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,6 +34,7 @@ #include "memory/allocation.inline.hpp" #include "utilities/decoder.hpp" #include "utilities/elfFile.hpp" +#include "utilities/elfFuncDescTable.hpp" #include "utilities/elfStringTable.hpp" #include "utilities/elfSymbolTable.hpp" @@ -43,6 +44,7 @@ ElfFile::ElfFile(const char* filepath) { memset(&m_elfHdr, 0, sizeof(m_elfHdr)); m_string_tables = NULL; m_symbol_tables = NULL; + m_funcDesc_table = NULL; m_next = NULL; m_status = NullDecoder::no_error; @@ -119,8 +121,8 @@ bool ElfFile::load_tables() { m_status = NullDecoder::file_invalid; return false; } - // string table if (shdr.sh_type == SHT_STRTAB) { + // string tables ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); if (table == NULL) { m_status = NullDecoder::out_of_memory; @@ -128,6 +130,7 @@ bool ElfFile::load_tables() { } add_string_table(table); } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { + // symbol tables ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); if (table == NULL) { m_status = NullDecoder::out_of_memory; @@ -136,6 +139,46 @@ bool ElfFile::load_tables() { add_symbol_table(table); } } + +#if defined(PPC64) + // Now read the .opd section wich contains the PPC64 function descriptor table. + // The .opd section is only available on PPC64 (see for example: + // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html) + // so this code should do no harm on other platforms but because of performance reasons we only + // execute it on PPC64 platforms. + // Notice that we can only find the .opd section after we have successfully read in the string + // tables in the previous loop, because we need to query the name of each section which is + // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx). + + // Reset the file pointer + if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { + m_status = NullDecoder::file_invalid; + return false; + } + for (int index = 0; index < m_elfHdr.e_shnum; index ++) { + if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { + m_status = NullDecoder::file_invalid; + return false; + } + if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) { + ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx); + if (string_table == NULL) { + m_status = NullDecoder::file_invalid; + return false; + } + char buf[8]; // '8' is enough because we only want to read ".opd" + if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) { + m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index); + if (m_funcDesc_table == NULL) { + m_status = NullDecoder::out_of_memory; + return false; + } + break; + } + } + } +#endif + } return true; } @@ -151,8 +194,9 @@ bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { int off = INT_MAX; bool found_symbol = false; while (symbol_table != NULL) { - if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { + if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) { found_symbol = true; + break; } symbol_table = symbol_table->m_next; } @@ -221,4 +265,4 @@ bool ElfFile::specifies_noexecstack() { } #endif -#endif // _WINDOWS +#endif // !_WINDOWS && !__APPLE__ diff --git a/hotspot/src/share/vm/utilities/elfFile.hpp b/hotspot/src/share/vm/utilities/elfFile.hpp index d6aa886bbbb..3ce8e92cc32 100644 --- a/hotspot/src/share/vm/utilities/elfFile.hpp +++ b/hotspot/src/share/vm/utilities/elfFile.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,6 +75,7 @@ typedef Elf32_Sym Elf_Sym; class ElfStringTable; class ElfSymbolTable; +class ElfFuncDescTable; // On Solaris/Linux platforms, libjvm.so does contain all private symbols. @@ -150,9 +151,12 @@ protected: // string tables ElfStringTable* m_string_tables; + // function descriptors table + ElfFuncDescTable* m_funcDesc_table; + NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // !_WINDOWS && !__APPLE__ #endif // SHARE_VM_UTILITIES_ELF_FILE_HPP diff --git a/hotspot/src/share/vm/utilities/elfFuncDescTable.cpp b/hotspot/src/share/vm/utilities/elfFuncDescTable.cpp new file mode 100644 index 00000000000..c5a00606d55 --- /dev/null +++ b/hotspot/src/share/vm/utilities/elfFuncDescTable.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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" + +#if !defined(_WINDOWS) && !defined(__APPLE__) + +#include "memory/allocation.inline.hpp" +#include "utilities/elfFuncDescTable.hpp" + +ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) { + assert(file, "null file handle"); + // The actual function address (i.e. function entry point) is always the + // first value in the function descriptor (on IA64 and PPC64 they look as follows): + // PPC64: [function entry point, TOC pointer, environment pointer] + // IA64 : [function entry point, GP (global pointer) value] + // Unfortunately 'shdr.sh_entsize' doesn't always seem to contain this size (it's zero on PPC64) so we can't assert + // assert(IA64_ONLY(2) PPC64_ONLY(3) * sizeof(address) == shdr.sh_entsize, "Size mismatch for '.opd' section entries"); + + m_funcDescs = NULL; + m_file = file; + m_index = index; + m_status = NullDecoder::no_error; + + // try to load the function descriptor table + long cur_offset = ftell(file); + if (cur_offset != -1) { + // call malloc so we can back up if memory allocation fails. + m_funcDescs = (address*)os::malloc(shdr.sh_size, mtInternal); + if (m_funcDescs) { + if (fseek(file, shdr.sh_offset, SEEK_SET) || + fread((void*)m_funcDescs, shdr.sh_size, 1, file) != 1 || + fseek(file, cur_offset, SEEK_SET)) { + m_status = NullDecoder::file_invalid; + os::free(m_funcDescs); + m_funcDescs = NULL; + } + } + if (!NullDecoder::is_error(m_status)) { + memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); + } + } else { + m_status = NullDecoder::file_invalid; + } +} + +ElfFuncDescTable::~ElfFuncDescTable() { + if (m_funcDescs != NULL) { + os::free(m_funcDescs); + } +} + +address ElfFuncDescTable::lookup(Elf_Word index) { + if (NullDecoder::is_error(m_status)) { + return NULL; + } + + if (m_funcDescs != NULL) { + if (m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size) { + // Notice that 'index' is a byte-offset into the function descriptor table. + return m_funcDescs[(index - m_shdr.sh_addr) / sizeof(address)]; + } + return NULL; + } else { + long cur_pos; + address addr; + if (!(m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size)) { + // don't put the whole decoder in error mode if we just tried a wrong index + return NULL; + } + if ((cur_pos = ftell(m_file)) == -1 || + fseek(m_file, m_shdr.sh_offset + index - m_shdr.sh_addr, SEEK_SET) || + fread(&addr, sizeof(addr), 1, m_file) != 1 || + fseek(m_file, cur_pos, SEEK_SET)) { + m_status = NullDecoder::file_invalid; + return NULL; + } + return addr; + } +} + +#endif // !_WINDOWS && !__APPLE__ diff --git a/hotspot/src/share/vm/utilities/elfFuncDescTable.hpp b/hotspot/src/share/vm/utilities/elfFuncDescTable.hpp new file mode 100644 index 00000000000..0b767a2c7b4 --- /dev/null +++ b/hotspot/src/share/vm/utilities/elfFuncDescTable.hpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP +#define SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP + +#if !defined(_WINDOWS) && !defined(__APPLE__) + + +#include "memory/allocation.hpp" +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" + +/* + +On PowerPC-64 (and other architectures like for example IA64) a pointer to a +function is not just a plain code address, but instead a pointer to a so called +function descriptor (which is simply a structure containing 3 pointers). +This fact is also reflected in the ELF ABI for PowerPC-64. + +On architectures like x86 or SPARC, the ELF symbol table contains the start +address and size of an object. So for example for a function object (i.e. type +'STT_FUNC') the symbol table's 'st_value' and 'st_size' fields directly +represent the starting address and size of that function. On PPC64 however, the +symbol table's 'st_value' field only contains an index into another, PPC64 +specific '.opd' (official procedure descriptors) section, while the 'st_size' +field still holds the size of the corresponding function. In order to get the +actual start address of a function, it is necessary to read the corresponding +function descriptor entry in the '.opd' section at the corresponding index and +extract the start address from there. + +That's exactly what this 'ElfFuncDescTable' class is used for. If the HotSpot +runs on a PPC64 machine, and the corresponding ELF files contains an '.opd' +section (which is actually mandatory on PPC64) it will be read into an object +of type 'ElfFuncDescTable' just like the string and symbol table sections. +Later on, during symbol lookup in 'ElfSymbolTable::lookup()' this function +descriptor table will be used if available to find the real function address. + +All this is how things work today (2013) on contemporary Linux distributions +(i.e. SLES 10) and new version of GCC (i.e. > 4.0). However there is a history, +and it goes like this: + +In SLES 9 times (sometimes before GCC 3.4) gcc/ld on PPC64 generated two +entries in the symbol table for every function. The value of the symbol with +the name of the function was the address of the function descriptor while the +dot '.' prefixed name was reserved to hold the actual address of that function +(http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES). + +For a C-function 'foo' this resulted in two symbol table entries like this +(extracted from the output of 'readelf -a '): + +Section Headers: + [ 9] .text PROGBITS 0000000000000a20 00000a20 + 00000000000005a0 0000000000000000 AX 0 0 16 + [21] .opd PROGBITS 00000000000113b8 000013b8 + 0000000000000138 0000000000000000 WA 0 0 8 + +Symbol table '.symtab' contains 86 entries: + Num: Value Size Type Bind Vis Ndx Name + 76: 00000000000114c0 24 FUNC GLOBAL DEFAULT 21 foo + 78: 0000000000000bb0 76 FUNC GLOBAL DEFAULT 9 .foo + +You can see now that the '.foo' entry actually points into the '.text' segment +('Ndx'=9) and its value and size fields represent the functions actual address +and size. On the other hand, the entry for plain 'foo' points into the '.opd' +section ('Ndx'=21) and its value and size fields are the index into the '.opd' +section and the size of the corresponding '.opd' section entry (3 pointers on +PPC64). + +These so called 'dot symbols' were dropped around gcc 3.4 from GCC and BINUTILS, +see http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html. +But nevertheless it may still be necessary to support both formats because we +either run on an old system or because it is possible at any time that functions +appear in the stack trace which come from old-style libraries. + +Therefore we not only have to check for the presence of the function descriptor +table during symbol lookup in 'ElfSymbolTable::lookup()'. We additionally have +to check that the symbol table entry references the '.opd' section. Only in +that case we can resolve the actual function address from there. Otherwise we +use the plain 'st_value' field from the symbol table as function address. This +way we can also lookup the symbols in old-style ELF libraries (although we get +the 'dotted' versions in that case). However, if present, the 'dot' will be +conditionally removed on PPC64 from the symbol in 'ElfDecoder::demangle()' in +decoder_linux.cpp. + +Notice that we can not reliably get the function address from old-style +libraries because the 'st_value' field of the symbol table entries which point +into the '.opd' section denote the size of the corresponding '.opd' entry and +not that of the corresponding function. This has changed for the symbol table +entries in new-style libraries as described at the beginning of this +documentation. + +*/ + +class ElfFuncDescTable: public CHeapObj { + friend class ElfFile; + public: + ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index); + ~ElfFuncDescTable(); + + // return the function address for the function descriptor at 'index' or NULL on error + address lookup(Elf_Word index); + + int get_index() { return m_index; }; + + NullDecoder::decoder_status get_status() { return m_status; }; + + protected: + // holds the complete function descriptor section if + // we can allocate enough memory + address* m_funcDescs; + + // file contains string table + FILE* m_file; + + // section header + Elf_Shdr m_shdr; + + // The section index of this function descriptor (i.e. '.opd') section in the ELF file + int m_index; + + NullDecoder::decoder_status m_status; +}; + +#endif // !_WINDOWS && !__APPLE__ + +#endif // SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP diff --git a/hotspot/src/share/vm/utilities/elfStringTable.cpp b/hotspot/src/share/vm/utilities/elfStringTable.cpp index 6a07a7db35c..5d6ad5f3026 100644 --- a/hotspot/src/share/vm/utilities/elfStringTable.cpp +++ b/hotspot/src/share/vm/utilities/elfStringTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * 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,4 +87,4 @@ bool ElfStringTable::string_at(int pos, char* buf, int buflen) { } } -#endif // _WINDOWS +#endif // !_WINDOWS && !__APPLE__ diff --git a/hotspot/src/share/vm/utilities/elfStringTable.hpp b/hotspot/src/share/vm/utilities/elfStringTable.hpp index bb671481b43..53a2fa03061 100644 --- a/hotspot/src/share/vm/utilities/elfStringTable.hpp +++ b/hotspot/src/share/vm/utilities/elfStringTable.hpp @@ -70,6 +70,6 @@ class ElfStringTable: CHeapObj { NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS and _APPLE +#endif // !_WINDOWS && !__APPLE__ #endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP diff --git a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp index 079c2b81da8..2c8c3c4da42 100644 --- a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp +++ b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * 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 @@ #if !defined(_WINDOWS) && !defined(__APPLE__) #include "memory/allocation.inline.hpp" +#include "utilities/elfFuncDescTable.hpp" #include "utilities/elfSymbolTable.hpp" ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) { @@ -68,7 +69,7 @@ ElfSymbolTable::~ElfSymbolTable() { } } -bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { +bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) { assert(stringtableIndex, "null string table index pointer"); assert(posIndex, "null string table offset pointer"); assert(offset, "null offset pointer"); @@ -77,19 +78,25 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, return false; } - address pc = 0; size_t sym_size = sizeof(Elf_Sym); assert((m_shdr.sh_size % sym_size) == 0, "check size"); int count = m_shdr.sh_size / sym_size; if (m_symbols != NULL) { for (int index = 0; index < count; index ++) { if (STT_FUNC == ELF_ST_TYPE(m_symbols[index].st_info)) { - address sym_addr = (address)m_symbols[index].st_value; - if (sym_addr < addr && (addr - sym_addr) < *offset) { - pc = (address)m_symbols[index].st_value; - *offset = (int)(addr - pc); + Elf_Word st_size = m_symbols[index].st_size; + address sym_addr; + if (funcDescTable != NULL && funcDescTable->get_index() == m_symbols[index].st_shndx) { + // We need to go another step trough the function descriptor table (currently PPC64 only) + sym_addr = funcDescTable->lookup(m_symbols[index].st_value); + } else { + sym_addr = (address)m_symbols[index].st_value; + } + if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) { + *offset = (int)(addr - sym_addr); *posIndex = m_symbols[index].st_name; *stringtableIndex = m_shdr.sh_link; + return true; } } } @@ -105,12 +112,19 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, for (int index = 0; index < count; index ++) { if (fread(&sym, sym_size, 1, m_file) == 1) { if (STT_FUNC == ELF_ST_TYPE(sym.st_info)) { - address sym_addr = (address)sym.st_value; - if (sym_addr < addr && (addr - sym_addr) < *offset) { - pc = (address)sym.st_value; - *offset = (int)(addr - pc); + Elf_Word st_size = sym.st_size; + address sym_addr; + if (funcDescTable != NULL && funcDescTable->get_index() == sym.st_shndx) { + // We need to go another step trough the function descriptor table (currently PPC64 only) + sym_addr = funcDescTable->lookup(sym.st_value); + } else { + sym_addr = (address)sym.st_value; + } + if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) { + *offset = (int)(addr - sym_addr); *posIndex = sym.st_name; *stringtableIndex = m_shdr.sh_link; + return true; } } } else { @@ -123,4 +137,4 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, return true; } -#endif // _WINDOWS +#endif // !_WINDOWS && !__APPLE__ diff --git a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp index b4e43fd1cd6..75d04e1ef00 100644 --- a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp +++ b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ class ElfSymbolTable: public CHeapObj { ~ElfSymbolTable(); // search the symbol that is nearest to the specified address. - bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); + bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable); NullDecoder::decoder_status get_status() { return m_status; }; @@ -65,6 +65,6 @@ class ElfSymbolTable: public CHeapObj { NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS and _APPLE +#endif // !_WINDOWS and !__APPLE__ #endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP From 46c4ef6572f4591e255883a8d6d7bb5b927de8fb Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 2 Dec 2013 10:26:14 +0100 Subject: [PATCH 043/265] 8029396: PPC64 (part 212): Several memory ordering fixes in C-code Memory ordering fixes in GC and other runtime code showing on PPC64. Reviewed-by: kvn, coleenp --- .../compactibleFreeListSpace.cpp | 26 +++++++++++++++++++ .../g1/g1SATBCardTableModRefBS.cpp | 3 ++- .../g1/g1SATBCardTableModRefBS.hpp | 2 +- hotspot/src/share/vm/memory/barrierSet.hpp | 4 +-- .../src/share/vm/memory/barrierSet.inline.hpp | 6 ++--- .../src/share/vm/memory/cardTableModRefBS.cpp | 4 +-- .../src/share/vm/memory/cardTableModRefBS.hpp | 11 +++++--- .../src/share/vm/memory/modRefBarrierSet.hpp | 2 +- hotspot/src/share/vm/oops/cpCache.cpp | 2 +- hotspot/src/share/vm/oops/cpCache.hpp | 21 ++++++++++----- hotspot/src/share/vm/oops/instanceKlass.cpp | 6 ++++- hotspot/src/share/vm/oops/method.hpp | 11 +++++--- hotspot/src/share/vm/oops/oop.inline.hpp | 16 +++++++++--- .../src/share/vm/runtime/biasedLocking.cpp | 6 +++-- hotspot/src/share/vm/runtime/sweeper.cpp | 3 ++- hotspot/src/share/vm/runtime/thread.hpp | 10 +++++-- 16 files changed, 99 insertions(+), 34 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index b87efd7bc2a..b86a875d745 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -997,6 +997,13 @@ size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { if (FreeChunk::indicatesFreeChunk(p)) { volatile FreeChunk* fc = (volatile FreeChunk*)p; size_t res = fc->size(); + + // Bugfix for systems with weak memory model (PPC64/IA64). The + // block's free bit was set and we have read the size of the + // block. Acquire and check the free bit again. If the block is + // still free, the read size is correct. + OrderAccess::acquire(); + // If the object is still a free chunk, return the size, else it // has been allocated so try again. if (FreeChunk::indicatesFreeChunk(p)) { @@ -1010,6 +1017,12 @@ size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { assert(k->is_klass(), "Should really be klass oop."); oop o = (oop)p; assert(o->is_oop(true /* ignore mark word */), "Should be an oop."); + + // Bugfix for systems with weak memory model (PPC64/IA64). + // The object o may be an array. Acquire to make sure that the array + // size (third word) is consistent. + OrderAccess::acquire(); + size_t res = o->size_given_klass(k); res = adjustObjectSize(res); assert(res != 0, "Block size should not be 0"); @@ -1040,6 +1053,13 @@ const { if (FreeChunk::indicatesFreeChunk(p)) { volatile FreeChunk* fc = (volatile FreeChunk*)p; size_t res = fc->size(); + + // Bugfix for systems with weak memory model (PPC64/IA64). The + // free bit of the block was set and we have read the size of + // the block. Acquire and check the free bit again. If the + // block is still free, the read size is correct. + OrderAccess::acquire(); + if (FreeChunk::indicatesFreeChunk(p)) { assert(res != 0, "Block size should not be 0"); assert(loops == 0, "Should be 0"); @@ -1055,6 +1075,12 @@ const { assert(k->is_klass(), "Should really be klass oop."); oop o = (oop)p; assert(o->is_oop(), "Should be an oop"); + + // Bugfix for systems with weak memory model (PPC64/IA64). + // The object o may be an array. Acquire to make sure that the array + // size (third word) is consistent. + OrderAccess::acquire(); + size_t res = o->size_given_klass(k); res = adjustObjectSize(res); assert(res != 0, "Block size should not be 0"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp index 9af87ed66a7..9f20a920b74 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp @@ -115,7 +115,8 @@ G1SATBCardTableLoggingModRefBS(MemRegion whole_heap, void G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field, - oop new_val) { + oop new_val, + bool release) { volatile jbyte* byte = byte_for(field); if (*byte == g1_young_gen) { return; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index a943c9f6db3..c670a841cd3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -151,7 +151,7 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { G1SATBCardTableModRefBS::is_a(bsn); } - void write_ref_field_work(void* field, oop new_val); + void write_ref_field_work(void* field, oop new_val, bool release = false); // Can be called from static contexts. static void write_ref_field_static(void* field, oop new_val); diff --git a/hotspot/src/share/vm/memory/barrierSet.hpp b/hotspot/src/share/vm/memory/barrierSet.hpp index 4fa307d3d09..13ff9b2738f 100644 --- a/hotspot/src/share/vm/memory/barrierSet.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.hpp @@ -100,9 +100,9 @@ protected: public: // ...then the post-write version. - inline void write_ref_field(void* field, oop new_val); + inline void write_ref_field(void* field, oop new_val, bool release = false); protected: - virtual void write_ref_field_work(void* field, oop new_val) = 0; + virtual void write_ref_field_work(void* field, oop new_val, bool release = false) = 0; public: // Invoke the barrier, if any, necessary when writing the "bytes"-byte diff --git a/hotspot/src/share/vm/memory/barrierSet.inline.hpp b/hotspot/src/share/vm/memory/barrierSet.inline.hpp index 01a78da8c8c..274614b48e5 100644 --- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp @@ -40,11 +40,11 @@ template void BarrierSet::write_ref_field_pre(T* field, oop new_val) { } } -void BarrierSet::write_ref_field(void* field, oop new_val) { +void BarrierSet::write_ref_field(void* field, oop new_val, bool release) { if (kind() == CardTableModRef) { - ((CardTableModRefBS*)this)->inline_write_ref_field(field, new_val); + ((CardTableModRefBS*)this)->inline_write_ref_field(field, new_val, release); } else { - write_ref_field_work(field, new_val); + write_ref_field_work(field, new_val, release); } } diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index 5e9d843ff52..9c53a88063d 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -419,8 +419,8 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) { // Note that these versions are precise! The scanning code has to handle the // fact that the write barrier may be either precise or imprecise. -void CardTableModRefBS::write_ref_field_work(void* field, oop newVal) { - inline_write_ref_field(field, newVal); +void CardTableModRefBS::write_ref_field_work(void* field, oop newVal, bool release) { + inline_write_ref_field(field, newVal, release); } diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp index cadb4cb88aa..1aa5b41ab14 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp @@ -292,7 +292,7 @@ public: // these functions here for performance. protected: void write_ref_field_work(oop obj, size_t offset, oop newVal); - virtual void write_ref_field_work(void* field, oop newVal); + virtual void write_ref_field_work(void* field, oop newVal, bool release = false); public: bool has_write_ref_array_opt() { return true; } @@ -324,9 +324,14 @@ public: template inline void inline_write_ref_field_pre(T* field, oop newVal) {} - template inline void inline_write_ref_field(T* field, oop newVal) { + template inline void inline_write_ref_field(T* field, oop newVal, bool release) { jbyte* byte = byte_for((void*)field); - *byte = dirty_card; + if (release) { + // Perform a releasing store if requested. + OrderAccess::release_store((volatile jbyte*) byte, dirty_card); + } else { + *byte = dirty_card; + } } // These are used by G1, when it uses the card table as a temporary data diff --git a/hotspot/src/share/vm/memory/modRefBarrierSet.hpp b/hotspot/src/share/vm/memory/modRefBarrierSet.hpp index 6c272b7b18b..951f05dc43e 100644 --- a/hotspot/src/share/vm/memory/modRefBarrierSet.hpp +++ b/hotspot/src/share/vm/memory/modRefBarrierSet.hpp @@ -60,7 +60,7 @@ public: void read_ref_field(void* field) {} void read_prim_field(HeapWord* field, size_t bytes) {} protected: - virtual void write_ref_field_work(void* field, oop new_val) = 0; + virtual void write_ref_field_work(void* field, oop new_val, bool release = false) = 0; public: void write_prim_field(HeapWord* field, size_t bytes, juint val1, juint val2) {} diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index c9bbb5fc4d9..5e93cd6c803 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -363,7 +363,7 @@ Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { // Decode the action of set_method and set_interface_call Bytecodes::Code invoke_code = bytecode_1(); if (invoke_code != (Bytecodes::Code)0) { - Metadata* f1 = (Metadata*)_f1; + Metadata* f1 = f1_ord(); if (f1 != NULL) { switch (invoke_code) { case Bytecodes::_invokeinterface: diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index 26079fdfdb1..49559be5e2e 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -138,7 +138,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { void set_bytecode_1(Bytecodes::Code code); void set_bytecode_2(Bytecodes::Code code); - void set_f1(Metadata* f1) { + void set_f1(Metadata* f1) { Metadata* existing_f1 = (Metadata*)_f1; // read once assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); _f1 = f1; @@ -325,14 +325,21 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { // Accessors int indices() const { return _indices; } + int indices_ord() const { return (intx)OrderAccess::load_ptr_acquire(&_indices); } int constant_pool_index() const { return (indices() & cp_index_mask); } - Bytecodes::Code bytecode_1() const { return Bytecodes::cast((indices() >> bytecode_1_shift) & bytecode_1_mask); } - Bytecodes::Code bytecode_2() const { return Bytecodes::cast((indices() >> bytecode_2_shift) & bytecode_2_mask); } - Method* f1_as_method() const { Metadata* f1 = (Metadata*)_f1; assert(f1 == NULL || f1->is_method(), ""); return (Method*)f1; } - Klass* f1_as_klass() const { Metadata* f1 = (Metadata*)_f1; assert(f1 == NULL || f1->is_klass(), ""); return (Klass*)f1; } - bool is_f1_null() const { Metadata* f1 = (Metadata*)_f1; return f1 == NULL; } // classifies a CPC entry as unbound + Bytecodes::Code bytecode_1() const { return Bytecodes::cast((indices_ord() >> bytecode_1_shift) & bytecode_1_mask); } + Bytecodes::Code bytecode_2() const { return Bytecodes::cast((indices_ord() >> bytecode_2_shift) & bytecode_2_mask); } + Metadata* f1_ord() const { return (Metadata *)OrderAccess::load_ptr_acquire(&_f1); } + Method* f1_as_method() const { Metadata* f1 = f1_ord(); assert(f1 == NULL || f1->is_method(), ""); return (Method*)f1; } + Klass* f1_as_klass() const { Metadata* f1 = f1_ord(); assert(f1 == NULL || f1->is_klass(), ""); return (Klass*)f1; } + // Use the accessor f1() to acquire _f1's value. This is needed for + // example in BytecodeInterpreter::run(), where is_f1_null() is + // called to check if an invokedynamic call is resolved. This load + // of _f1 must be ordered with the loads performed by + // cache->main_entry_index(). + bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; } - Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } + Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); } int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); } bool is_volatile() const { return (_flags & (1 << is_volatile_shift)) != 0; } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 5077f123e38..0c5c7a23cb6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1203,7 +1203,11 @@ void InstanceKlass::mask_for(methodHandle method, int bci, MutexLocker x(OopMapCacheAlloc_lock); // First time use. Allocate a cache in C heap if (_oop_map_cache == NULL) { - _oop_map_cache = new OopMapCache(); + // Release stores from OopMapCache constructor before assignment + // to _oop_map_cache. C++ compilers on ppc do not emit the + // required memory barrier only because of the volatile + // qualifier of _oop_map_cache. + OrderAccess::release_store_ptr(&_oop_map_cache, new OopMapCache()); } } // _oop_map_cache is constant after init; lookup below does is own locking. diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 63705b3cc26..3f581939119 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -350,16 +350,21 @@ class Method : public Metadata { } void set_method_data(MethodData* data) { - _method_data = data; + // The store into method must be released. On platforms without + // total store order (TSO) the reference may become visible before + // the initialization of data otherwise. + OrderAccess::release_store_ptr((volatile void *)&_method_data, data); } MethodCounters* method_counters() const { return _method_counters; } - void set_method_counters(MethodCounters* counters) { - _method_counters = counters; + // The store into method must be released. On platforms without + // total store order (TSO) the reference may become visible before + // the initialization of data otherwise. + OrderAccess::release_store_ptr((volatile void *)&_method_counters, counters); } #ifdef TIERED diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 0a297483486..4e81252b548 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -490,9 +490,9 @@ inline int oopDesc::size() { return size_given_klass(klass()); } -inline void update_barrier_set(void* p, oop v) { +inline void update_barrier_set(void* p, oop v, bool release = false) { assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); - oopDesc::bs()->write_ref_field(p, v); + oopDesc::bs()->write_ref_field(p, v, release); } template inline void update_barrier_set_pre(T* p, oop v) { @@ -505,7 +505,10 @@ template inline void oop_store(T* p, oop v) { } else { update_barrier_set_pre(p, v); oopDesc::encode_store_heap_oop(p, v); - update_barrier_set((void*)p, v); // cast away type + // always_do_update_barrier == false => + // Either we are at a safepoint (in GC) or CMS is not used. In both + // cases it's unnecessary to mark the card as dirty with release sematics. + update_barrier_set((void*)p, v, false /* release */); // cast away type } } @@ -513,7 +516,12 @@ template inline void oop_store(volatile T* p, oop v) { update_barrier_set_pre((T*)p, v); // cast away volatile // Used by release_obj_field_put, so use release_store_ptr. oopDesc::release_encode_store_heap_oop(p, v); - update_barrier_set((void*)p, v); // cast away type + // When using CMS we must mark the card corresponding to p as dirty + // with release sematics to prevent that CMS sees the dirty card but + // not the new value v at p due to reordering of the two + // stores. Note that CMS has a concurrent precleaning phase, where + // it reads the card table while the Java threads are running. + update_barrier_set((void*)p, v, true /* release */); // cast away type } // Should replace *addr = oop assignments where addr type depends on UseCompressedOops diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp index 2ac4da03f5e..42e4899b251 100644 --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp @@ -233,8 +233,10 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ // Fix up highest lock to contain displaced header and point // object at it highest_lock->set_displaced_header(unbiased_prototype); - // Reset object header to point to displaced mark - obj->set_mark(markOopDesc::encode(highest_lock)); + // Reset object header to point to displaced mark. + // Must release storing the lock address for platforms without TSO + // ordering (e.g. ppc). + obj->release_set_mark(markOopDesc::encode(highest_lock)); assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit"); if (TraceBiasedLocking && (Verbose || !is_bulk)) { tty->print_cr(" Revoked bias of currently-locked object"); diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index 9034428173e..e340bac8b82 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -299,7 +299,8 @@ void NMethodSweeper::possibly_sweep() { _bytes_changed = 0; } } - _sweep_started = 0; + // Release work, because another compiler thread could continue. + OrderAccess::release_store((int*)&_sweep_started, 0); } } diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 565fafc2866..94cca352c26 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1044,8 +1044,14 @@ class JavaThread: public Thread { address last_Java_pc(void) { return _anchor.last_Java_pc(); } // Safepoint support - JavaThreadState thread_state() const { return _thread_state; } - void set_thread_state(JavaThreadState s) { _thread_state=s; } + // Use membars when accessing volatile _thread_state. See + // Threads::create_vm() for size checks. + JavaThreadState thread_state() const { + return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state); + } + void set_thread_state(JavaThreadState s) { + OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s); + } ThreadSafepointState *safepoint_state() const { return _safepoint_state; } void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; } bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); } From c50c083f836049bb454d84cee1d5b75215789732 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Tue, 10 Dec 2013 14:29:43 +0100 Subject: [PATCH 044/265] 8029888: PPC64: (part 219): adl replacement variable CondRegister Add support for replacement variable CondRegister in adlc. Reviewed-by: kvn --- hotspot/src/share/vm/adlc/output_c.cpp | 1 + hotspot/src/share/vm/memory/metaspace.hpp | 2 -- hotspot/src/share/vm/opto/machnode.hpp | 9 +++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index a6c3bcbf789..d12d0378411 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -2315,6 +2315,7 @@ private: #if defined(IA32) || defined(AMD64) if (strcmp(rep_var,"$XMMRegister") == 0) return "as_XMMRegister"; #endif + if (strcmp(rep_var,"$CondRegister") == 0) return "as_ConditionRegister"; return NULL; } diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp index 30826d96564..b98e69a4123 100644 --- a/hotspot/src/share/vm/memory/metaspace.hpp +++ b/hotspot/src/share/vm/memory/metaspace.hpp @@ -117,12 +117,10 @@ class Metaspace : public CHeapObj { // Aligned size of the metaspace. static size_t _compressed_class_space_size; - public: static size_t compressed_class_space_size() { return _compressed_class_space_size; } - private: static void set_compressed_class_space_size(size_t size) { _compressed_class_space_size = size; } diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 35498dbd5f5..5ea42a43fce 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -103,6 +103,15 @@ public: return ::as_XMMRegister(reg(ra_, node, idx)); } #endif + // CondRegister reg converter +#if defined(PPC64) + ConditionRegister as_ConditionRegister(PhaseRegAlloc *ra_, const Node *node) const { + return ::as_ConditionRegister(reg(ra_, node)); + } + ConditionRegister as_ConditionRegister(PhaseRegAlloc *ra_, const Node *node, int idx) const { + return ::as_ConditionRegister(reg(ra_, node, idx)); + } +#endif virtual intptr_t constant() const; virtual relocInfo::relocType constant_reloc() const; From 0bc1701ea015d34507572de3296294832fd9045e Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 31 Jan 2014 09:55:59 +0100 Subject: [PATCH 045/265] 8032771: The flag VerifySilently misses a test case Add test case for the VerifySilently flag. Reviewed-by: brutisso --- hotspot/test/gc/TestVerifySilently.java | 84 +++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 hotspot/test/gc/TestVerifySilently.java diff --git a/hotspot/test/gc/TestVerifySilently.java b/hotspot/test/gc/TestVerifySilently.java new file mode 100644 index 00000000000..deefd4863e4 --- /dev/null +++ b/hotspot/test/gc/TestVerifySilently.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test TestVerifySilently.java + * @key gc + * @bug 8032771 + * @summary Test silent verification. + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import java.util.ArrayList; +import java.util.Collections; + +class RunSystemGC { + public static void main(String args[]) throws Exception { + System.gc(); + } +} + + +public class TestVerifySilently { + private static String[] getTestJavaOpts() { + String testVmOptsStr = System.getProperty("test.java.opts"); + if (!testVmOptsStr.isEmpty()) { + return testVmOptsStr.split(" "); + } else { + return new String[] {}; + } + } + + private static OutputAnalyzer runTest(boolean verifySilently) throws Exception { + ArrayList vmOpts = new ArrayList(); + + Collections.addAll(vmOpts, getTestJavaOpts()); + Collections.addAll(vmOpts, new String[] {"-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerifyDuringStartup", + "-XX:+VerifyBeforeGC", + "-XX:+VerifyAfterGC", + "-XX:" + (verifySilently ? "+":"-") + "VerifySilently", + RunSystemGC.class.getName()}); + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("Output:\n" + output.getOutput()); + return output; + } + + + public static void main(String args[]) throws Exception { + + OutputAnalyzer output; + + output = runTest(false); + output.shouldContain("[Verifying"); + output.shouldHaveExitValue(0); + + output = runTest(true); + output.shouldNotContain("[Verifying"); + output.shouldHaveExitValue(0); + } +} From 90c553c06f5185ba97d8a7c79f26e32ded11b360 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 31 Jan 2014 09:57:50 +0100 Subject: [PATCH 046/265] 6991197: G1: specialize deal_with_reference() for narrowOop* Clean up and slightly optimize reference handling from the GC reference task queue. Since we never push partial array chunks as narrowOop* we can manually specialize the code so that some code can be optimized away. Reviewed-by: tonyp, brutisso, stefank --- .../vm/gc_implementation/g1/g1OopClosures.hpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 414b82f95bc..bda11dc6b98 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,13 +86,26 @@ public: #define G1_PARTIAL_ARRAY_MASK 0x2 -template inline bool has_partial_array_mask(T* ref) { +inline bool has_partial_array_mask(oop* ref) { return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK; } -template inline T* set_partial_array_mask(T obj) { +// We never encode partial array oops as narrowOop*, so return false immediately. +// This allows the compiler to create optimized code when popping references from +// the work queue. +inline bool has_partial_array_mask(narrowOop* ref) { + assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*"); + return false; +} + +// Only implement set_partial_array_mask() for regular oops, not for narrowOops. +// We always encode partial arrays as regular oop, to allow the +// specialization for has_partial_array_mask() for narrowOops above. +// This means that unintentional use of this method with narrowOops are caught +// by the compiler. +inline oop* set_partial_array_mask(oop obj) { assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!"); - return (T*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK); + return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK); } template inline oop clear_partial_array_mask(T* ref) { From 58f7d4c7e56503c97b6cf9fd751aea07c508286a Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 31 Jan 2014 09:58:06 +0100 Subject: [PATCH 047/265] 8033106: Wrong predicate for checking whether the correct amount of symbol table entries have been processed in G1 The change fixes the predicate check. Reviewed-by: jmasa, tonyp, stefank --- hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index ba1fab4ffcd..4f638f447c3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5222,7 +5222,7 @@ public: guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size, err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT, StringTable::parallel_claimed_index(), _initial_string_table_size)); - guarantee(!_process_strings || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, + guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT, SymbolTable::parallel_claimed_index(), _initial_symbol_table_size)); } From c50ff2e023b65e4fee3d3349a0ef98ba5e6cbab1 Mon Sep 17 00:00:00 2001 From: Shrinivas Joshi Date: Thu, 16 Jan 2014 13:25:25 -0800 Subject: [PATCH 048/265] 8024366: Make UseNUMA enable UseNUMAInterleaving Reviewed-by: brutisso, tschatzl --- hotspot/src/share/vm/runtime/arguments.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index b0289b9d588..ca52c8d4a7b 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3823,18 +3823,24 @@ jint Arguments::apply_ergo() { } jint Arguments::adjust_after_os() { -#if INCLUDE_ALL_GCS - if (UseParallelGC || UseParallelOldGC) { - if (UseNUMA) { + if (UseNUMA) { + if (UseParallelGC || UseParallelOldGC) { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { - FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M); + FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M); } - // For those collectors or operating systems (eg, Windows) that do - // not support full UseNUMA, we will map to UseNUMAInterleaving for now - UseNUMAInterleaving = true; + } + // UseNUMAInterleaving is set to ON for all collectors and + // platforms when UseNUMA is set to ON. NUMA-aware collectors + // such as the parallel collector for Linux and Solaris will + // interleave old gen and survivor spaces on top of NUMA + // allocation policy for the eden space. + // Non NUMA-aware collectors such as CMS, G1 and Serial-GC on + // all platforms and ParallelGC on Windows will interleave all + // of the heap spaces across NUMA nodes. + if (FLAG_IS_DEFAULT(UseNUMAInterleaving)) { + FLAG_SET_ERGO(bool, UseNUMAInterleaving, true); } } -#endif // INCLUDE_ALL_GCS return JNI_OK; } From 814dad45e077b59b58f03e0d512c5774839b22f3 Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Wed, 5 Feb 2014 10:09:54 +0100 Subject: [PATCH 049/265] 8028254: gc/arguments/TestMinInitialErgonomics.java failed with unexpected initial heap size Reviewed-by: brutisso, tschatzl, sjohanss --- hotspot/src/share/vm/prims/whitebox.cpp | 2 +- .../test/gc/arguments/TestMaxHeapSizeTools.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 1cb799b3ea9..56919990889 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -105,7 +105,7 @@ WB_END WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) { CollectorPolicy * p = Universe::heap()->collector_policy(); gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " - SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Min alignment "SIZE_FORMAT" Max alignment "SIZE_FORMAT, + SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Space alignment "SIZE_FORMAT" Heap alignment "SIZE_FORMAT, p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(), p->space_alignment(), p->heap_alignment()); } diff --git a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java index 0e07f794194..b5859b5cf49 100644 --- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java +++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java @@ -41,8 +41,8 @@ final class MinInitialMaxValues { public long initialHeapSize; public long maxHeapSize; - public long minAlignment; - public long maxAlignment; + public long spaceAlignment; + public long heapAlignment; } class TestMaxHeapSizeTools { @@ -192,7 +192,7 @@ class TestMaxHeapSizeTools { // Unfortunately there is no other way to retrieve the minimum heap size and // the alignments. - Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Min alignment \\d+ Max alignment \\d+"). + Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Space alignment \\d+ Heap alignment \\d+"). matcher(output.getStdout()); if (!m.find()) { throw new RuntimeException("Could not find heap size string."); @@ -204,8 +204,8 @@ class TestMaxHeapSizeTools { val.minHeapSize = valueAfter(match, "Minimum heap "); val.initialHeapSize = valueAfter(match, "Initial heap "); val.maxHeapSize = valueAfter(match, "Maximum heap "); - val.minAlignment = valueAfter(match, "Min alignment "); - val.maxAlignment = valueAfter(match, "Max alignment "); + val.spaceAlignment = valueAfter(match, "Space alignment "); + val.heapAlignment = valueAfter(match, "Heap alignment "); } /** @@ -218,12 +218,12 @@ class TestMaxHeapSizeTools { MinInitialMaxValues v = new MinInitialMaxValues(); getMinInitialMaxHeap(args, v); - if ((expectedMin != -1) && (align_up(expectedMin, v.minAlignment) != v.minHeapSize)) { + if ((expectedMin != -1) && (align_up(expectedMin, v.heapAlignment) != v.minHeapSize)) { throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize + " differs from expected minimum heap size of " + expectedMin); } - if ((expectedInitial != -1) && (align_up(expectedInitial, v.minAlignment) != v.initialHeapSize)) { + if ((expectedInitial != -1) && (align_up(expectedInitial, v.heapAlignment) != v.initialHeapSize)) { throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize + " differs from expected initial heap size of " + expectedInitial); } @@ -247,7 +247,7 @@ class TestMaxHeapSizeTools { MinInitialMaxValues v = new MinInitialMaxValues(); getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v); - long expectedHeapSize = align_up(maxHeapsize * K * K, v.maxAlignment); + long expectedHeapSize = align_up(maxHeapsize * K * K, v.heapAlignment); long actualHeapSize = v.maxHeapSize; if (actualHeapSize > expectedHeapSize) { From 170566f471ad6091d79242e6aa974825fffc1524 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 5 Feb 2014 12:47:48 +0100 Subject: [PATCH 050/265] 8033601: G1: Make array chunking use the same length field as the other young GCs Use the old copy length instead of the length of the forwarded object for chunked arrays. Reviewed-by: brutisso, tschatzl --- .../gc_implementation/g1/g1CollectedHeap.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 4f638f447c3..7c70480183f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4764,9 +4764,9 @@ oop G1ParCopyClosure if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { // We keep track of the next start index in the length field of - // the to-space object. The actual length can be found in the - // length field of the from-space object. - arrayOop(obj)->set_length(0); + // the from-space object. The actual length can be found in the + // length field of the to-space object. + arrayOop(old)->set_length(0); oop* old_p = set_partial_array_mask(old); _par_scan_state->push_on_queue(old_p); } else { @@ -4840,16 +4840,16 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap."); assert(from_obj->is_objArray(), "must be obj array"); objArrayOop from_obj_array = objArrayOop(from_obj); - // The from-space object contains the real length. - int length = from_obj_array->length(); + // We keep track of the next start index in the length field of the + // from-space object. + int next_index = from_obj_array->length(); assert(from_obj->is_forwarded(), "must be forwarded"); oop to_obj = from_obj->forwardee(); assert(from_obj != to_obj, "should not be chunking self-forwarded objects"); objArrayOop to_obj_array = objArrayOop(to_obj); - // We keep track of the next start index in the length field of the - // to-space object. - int next_index = to_obj_array->length(); + // The to-space object contains the real length. + int length = to_obj_array->length(); assert(0 <= next_index && next_index < length, err_msg("invariant, next index: %d, length: %d", next_index, length)); @@ -4859,7 +4859,7 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { // We'll try not to push a range that's smaller than ParGCArrayScanChunk. if (remainder > 2 * ParGCArrayScanChunk) { end = start + ParGCArrayScanChunk; - to_obj_array->set_length(end); + from_obj_array->set_length(end); // Push the remainder before we process the range in case another // worker has run out of things to do and can steal it. oop* from_obj_p = set_partial_array_mask(from_obj); @@ -4868,7 +4868,7 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { assert(length == end, "sanity"); // We'll process the final range for this object. Restore the length // so that the heap remains parsable in case of evacuation failure. - to_obj_array->set_length(end); + from_obj_array->set_length(end); } _scanner.set_region(_g1->heap_region_containing_raw(to_obj)); // Process indexes [start,end). It will also process the header From a81e7a52fc997c7bfdb8cf98faa4f779749cf682 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 5 Feb 2014 14:29:34 +0100 Subject: [PATCH 051/265] 8033443: Test8000311 fails after latest changes to parallelize string and symbol table unlink When string and symbol table unlink are not performed in parallel, the claim index we check is not updated, and so a guarantee fails. Take this into account when checking the guarantee. Reviewed-by: brutisso, jwilhelm --- .../share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 7c70480183f..ec2813244ec 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -5202,9 +5202,12 @@ private: bool _process_symbols; int _symbols_processed; int _symbols_removed; + + bool _do_in_parallel; public: G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) : AbstractGangTask("Par String/Symbol table unlink"), _is_alive(is_alive), + _do_in_parallel(G1CollectedHeap::use_parallel_gc_threads()), _process_strings(process_strings), _strings_processed(0), _strings_removed(0), _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) { @@ -5219,16 +5222,16 @@ public: } ~G1StringSymbolTableUnlinkTask() { - guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size, + guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size, err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT, StringTable::parallel_claimed_index(), _initial_string_table_size)); - guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, + guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT, SymbolTable::parallel_claimed_index(), _initial_symbol_table_size)); } void work(uint worker_id) { - if (G1CollectedHeap::use_parallel_gc_threads()) { + if (_do_in_parallel) { int strings_processed = 0; int strings_removed = 0; int symbols_processed = 0; From 0a63fe1c101abc1f87db22d2cf319c9d98f15995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Lid=C3=A9n?= Date: Thu, 6 Feb 2014 14:12:43 +0100 Subject: [PATCH 052/265] 8031703: Missing post-barrier in ReferenceProcessor Reviewed-by: tonyp, tschatzl --- .../gc_implementation/g1/g1CollectedHeap.cpp | 2 +- .../share/vm/memory/referenceProcessor.cpp | 44 +++++++++---------- .../share/vm/memory/referenceProcessor.hpp | 17 ++++--- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index ec2813244ec..5fab3d84f96 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2266,7 +2266,7 @@ void G1CollectedHeap::ref_processing_init() { // (for efficiency/performance) false); // Setting next fields of discovered - // lists requires a barrier. + // lists does not require a barrier. } size_t G1CollectedHeap::capacity() const { diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index f6a48ee99b9..d7d48ba7548 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -95,11 +95,11 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, uint mt_discovery_degree, bool atomic_discovery, BoolObjectClosure* is_alive_non_header, - bool discovered_list_needs_barrier) : + bool discovered_list_needs_post_barrier) : _discovering_refs(false), _enqueuing_is_done(false), _is_alive_non_header(is_alive_non_header), - _discovered_list_needs_barrier(discovered_list_needs_barrier), + _discovered_list_needs_post_barrier(discovered_list_needs_post_barrier), _processing_is_mt(mt_processing), _next_id(0) { @@ -490,13 +490,13 @@ void DiscoveredListIterator::remove() { } else { new_next = _next; } - - if (UseCompressedOops) { - // Remove Reference object from list. - oopDesc::encode_store_heap_oop((narrowOop*)_prev_next, new_next); - } else { - // Remove Reference object from list. - oopDesc::store_heap_oop((oop*)_prev_next, new_next); + // Remove Reference object from discovered list. Note that G1 does not need a + // pre-barrier here because we know the Reference has already been found/marked, + // that's how it ended up in the discovered list in the first place. + oop_store_raw(_prev_next, new_next); + if (_discovered_list_needs_post_barrier && _prev_next != _refs_list.adr_head()) { + // Needs post-barrier and this is not the list head (which is not on the heap) + oopDesc::bs()->write_ref_field(_prev_next, new_next); } NOT_PRODUCT(_removed++); _refs_list.dec_length(1); @@ -544,7 +544,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list, OopClosure* keep_alive, VoidClosure* complete_gc) { assert(policy != NULL, "Must have a non-NULL policy"); - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, _discovered_list_needs_post_barrier); // Decide which softly reachable refs should be kept alive. while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -584,7 +584,7 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive) { assert(discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, _discovered_list_needs_post_barrier); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());) @@ -621,7 +621,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, OopClosure* keep_alive, VoidClosure* complete_gc) { assert(!discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, _discovered_list_needs_post_barrier); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); @@ -664,7 +664,7 @@ ReferenceProcessor::process_phase3(DiscoveredList& refs_list, OopClosure* keep_alive, VoidClosure* complete_gc) { ResourceMark rm; - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, _discovered_list_needs_post_barrier); while (iter.has_next()) { iter.update_discovered(); iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); @@ -782,8 +782,8 @@ private: void ReferenceProcessor::set_discovered(oop ref, oop value) { java_lang_ref_Reference::set_discovered_raw(ref, value); - if (_discovered_list_needs_barrier) { - oopDesc::bs()->write_ref_field(ref, value); + if (_discovered_list_needs_post_barrier) { + oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(ref), value); } } @@ -980,7 +980,7 @@ void ReferenceProcessor::clean_up_discovered_references() { void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) { assert(!discovery_is_atomic(), "Else why call this method?"); - DiscoveredListIterator iter(refs_list, NULL, NULL); + DiscoveredListIterator iter(refs_list, NULL, NULL, _discovered_list_needs_post_barrier); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); oop next = java_lang_ref_Reference::next(iter.obj()); @@ -1076,7 +1076,7 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, // elided this out for G1, but left in the test for some future // collector that might have need for a pre-barrier here, e.g.:- // oopDesc::bs()->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); - assert(!_discovered_list_needs_barrier || UseG1GC, + assert(!_discovered_list_needs_post_barrier || UseG1GC, "Need to check non-G1 collector: " "may need a pre-write-barrier for CAS from NULL below"); oop retest = oopDesc::atomic_compare_exchange_oop(next_discovered, discovered_addr, @@ -1087,7 +1087,7 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, // is necessary. refs_list.set_head(obj); refs_list.inc_length(1); - if (_discovered_list_needs_barrier) { + if (_discovered_list_needs_post_barrier) { oopDesc::bs()->write_ref_field((void*)discovered_addr, next_discovered); } @@ -1240,7 +1240,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { if (_discovery_is_mt) { add_to_discovered_list_mt(*list, obj, discovered_addr); } else { - // If "_discovered_list_needs_barrier", we do write barriers when + // If "_discovered_list_needs_post_barrier", we do write barriers when // updating the discovered reference list. Otherwise, we do a raw store // here: the field will be visited later when processing the discovered // references. @@ -1252,10 +1252,10 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { // pre-value, we can safely elide the pre-barrier here for the case of G1. // e.g.:- oopDesc::bs()->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); assert(discovered == NULL, "control point invariant"); - assert(!_discovered_list_needs_barrier || UseG1GC, + assert(!_discovered_list_needs_post_barrier || UseG1GC, "For non-G1 collector, may need a pre-write-barrier for CAS from NULL below"); oop_store_raw(discovered_addr, next_discovered); - if (_discovered_list_needs_barrier) { + if (_discovered_list_needs_post_barrier) { oopDesc::bs()->write_ref_field((void*)discovered_addr, next_discovered); } list->set_head(obj); @@ -1351,7 +1351,7 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { - DiscoveredListIterator iter(refs_list, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive, _discovered_list_needs_post_barrier); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); oop obj = iter.obj(); diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index 63b3556bfdd..f9f69f07142 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -99,6 +99,7 @@ private: oop _referent; OopClosure* _keep_alive; BoolObjectClosure* _is_alive; + bool _discovered_list_needs_post_barrier; DEBUG_ONLY( oop _first_seen; // cyclic linked list check @@ -112,7 +113,8 @@ private: public: inline DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive): + BoolObjectClosure* is_alive, + bool discovered_list_needs_post_barrier = false): _refs_list(refs_list), _prev_next(refs_list.adr_head()), _prev(NULL), @@ -126,7 +128,8 @@ public: #endif _next(NULL), _keep_alive(keep_alive), - _is_alive(is_alive) + _is_alive(is_alive), + _discovered_list_needs_post_barrier(discovered_list_needs_post_barrier) { } // End Of List. @@ -228,12 +231,12 @@ class ReferenceProcessor : public CHeapObj { bool _discovery_is_mt; // true if reference discovery is MT. // If true, setting "next" field of a discovered refs list requires - // write barrier(s). (Must be true if used in a collector in which + // write post barrier. (Must be true if used in a collector in which // elements of a discovered list may be moved during discovery: for // example, a collector like Garbage-First that moves objects during a // long-term concurrent marking phase that does weak reference // discovery.) - bool _discovered_list_needs_barrier; + bool _discovered_list_needs_post_barrier; bool _enqueuing_is_done; // true if all weak references enqueued bool _processing_is_mt; // true during phases when @@ -380,8 +383,8 @@ class ReferenceProcessor : public CHeapObj { protected: // Set the 'discovered' field of the given reference to - // the given value - emitting barriers depending upon - // the value of _discovered_list_needs_barrier. + // the given value - emitting post barriers depending upon + // the value of _discovered_list_needs_post_barrier. void set_discovered(oop ref, oop value); // "Preclean" the given discovered reference list @@ -425,7 +428,7 @@ class ReferenceProcessor : public CHeapObj { bool mt_discovery = false, uint mt_discovery_degree = 1, bool atomic_discovery = true, BoolObjectClosure* is_alive_non_header = NULL, - bool discovered_list_needs_barrier = false); + bool discovered_list_needs_post_barrier = false); // RefDiscoveryPolicy values enum DiscoveryPolicy { From b109e793aaabc52a60f097f01a33c75919f4b729 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 6 Feb 2014 17:12:10 +0100 Subject: [PATCH 053/265] 8033545: Missing volatile specifier in Bitmap::par_put_range_within_word The method Bitmap::par_put_range_within_word reloads the original value during a CAS, which may be optimized away. Instead of reloading, use the value returned by Atomic::cmpxchg_ptr() for further processing. Reviewed-by: tschatzl, brutisso, tonyp --- hotspot/src/share/vm/utilities/bitMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index b6760488709..8431395a6ba 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -107,7 +107,7 @@ void BitMap::par_put_range_within_word(idx_t beg, idx_t end, bool value) { while (true) { intptr_t res = Atomic::cmpxchg_ptr(nw, pw, w); if (res == w) break; - w = *pw; + w = res; nw = value ? (w | ~mr) : (w & mr); } } From 980e57c6c423c671c90f00b73de243cfd37c5d97 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Fri, 7 Feb 2014 13:48:07 +0100 Subject: [PATCH 054/265] 8033922: G1: Back out 8033601 and go back to use the to-obj for chunked arrays Reviewed-by: stefank, tschatzl --- .../gc_implementation/g1/g1CollectedHeap.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 5fab3d84f96..a56b4ec0c23 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4764,9 +4764,9 @@ oop G1ParCopyClosure if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { // We keep track of the next start index in the length field of - // the from-space object. The actual length can be found in the - // length field of the to-space object. - arrayOop(old)->set_length(0); + // the to-space object. The actual length can be found in the + // length field of the from-space object. + arrayOop(obj)->set_length(0); oop* old_p = set_partial_array_mask(old); _par_scan_state->push_on_queue(old_p); } else { @@ -4840,16 +4840,16 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap."); assert(from_obj->is_objArray(), "must be obj array"); objArrayOop from_obj_array = objArrayOop(from_obj); - // We keep track of the next start index in the length field of the - // from-space object. - int next_index = from_obj_array->length(); + // The from-space object contains the real length. + int length = from_obj_array->length(); assert(from_obj->is_forwarded(), "must be forwarded"); oop to_obj = from_obj->forwardee(); assert(from_obj != to_obj, "should not be chunking self-forwarded objects"); objArrayOop to_obj_array = objArrayOop(to_obj); - // The to-space object contains the real length. - int length = to_obj_array->length(); + // We keep track of the next start index in the length field of the + // to-space object. + int next_index = to_obj_array->length(); assert(0 <= next_index && next_index < length, err_msg("invariant, next index: %d, length: %d", next_index, length)); @@ -4859,7 +4859,7 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { // We'll try not to push a range that's smaller than ParGCArrayScanChunk. if (remainder > 2 * ParGCArrayScanChunk) { end = start + ParGCArrayScanChunk; - from_obj_array->set_length(end); + to_obj_array->set_length(end); // Push the remainder before we process the range in case another // worker has run out of things to do and can steal it. oop* from_obj_p = set_partial_array_mask(from_obj); @@ -4868,7 +4868,7 @@ template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { assert(length == end, "sanity"); // We'll process the final range for this object. Restore the length // so that the heap remains parsable in case of evacuation failure. - from_obj_array->set_length(end); + to_obj_array->set_length(end); } _scanner.set_region(_g1->heap_region_containing_raw(to_obj)); // Process indexes [start,end). It will also process the header From a26a6715b00b0e79dc2f568f2e740aa6ad9218bc Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 10 Feb 2014 12:51:51 +0100 Subject: [PATCH 055/265] 8033764: Remove the usage of StarTask from BufferingOopClosure Reviewed-by: mgerdin, brutisso, tschatzl --- .../g1/bufferingOopClosure.cpp | 271 ++++++++++++++++++ .../g1/bufferingOopClosure.hpp | 113 +++++--- .../vm/gc_implementation/g1/g1RemSet.cpp | 1 - .../vm/gc_implementation/g1/g1RemSet.hpp | 2 +- hotspot/src/share/vm/prims/jni.cpp | 2 + 5 files changed, 352 insertions(+), 37 deletions(-) create mode 100644 hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp diff --git a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp new file mode 100644 index 00000000000..d1edd60da9d --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/bufferingOopClosure.hpp" +#include "memory/iterator.hpp" +#include "utilities/debug.hpp" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class TestBufferingOopClosure { + + // Helper class to fake a set of oop*s and narrowOop*s. + class FakeRoots { + public: + // Used for sanity checking of the values passed to the do_oops functions in the test. + static const uintptr_t NarrowOopMarker = uintptr_t(1) << (BitsPerWord -1); + + int _num_narrow; + int _num_full; + void** _narrow; + void** _full; + + FakeRoots(int num_narrow, int num_full) : + _num_narrow(num_narrow), + _num_full(num_full), + _narrow((void**)::malloc(sizeof(void*) * num_narrow)), + _full((void**)::malloc(sizeof(void*) * num_full)) { + + for (int i = 0; i < num_narrow; i++) { + _narrow[i] = (void*)(NarrowOopMarker + (uintptr_t)i); + } + for (int i = 0; i < num_full; i++) { + _full[i] = (void*)(uintptr_t)i; + } + } + + ~FakeRoots() { + ::free(_narrow); + ::free(_full); + } + + void oops_do_narrow_then_full(OopClosure* cl) { + for (int i = 0; i < _num_narrow; i++) { + cl->do_oop((narrowOop*)_narrow[i]); + } + for (int i = 0; i < _num_full; i++) { + cl->do_oop((oop*)_full[i]); + } + } + + void oops_do_full_then_narrow(OopClosure* cl) { + for (int i = 0; i < _num_full; i++) { + cl->do_oop((oop*)_full[i]); + } + for (int i = 0; i < _num_narrow; i++) { + cl->do_oop((narrowOop*)_narrow[i]); + } + } + + void oops_do_mixed(OopClosure* cl) { + int i; + for (i = 0; i < _num_full && i < _num_narrow; i++) { + cl->do_oop((oop*)_full[i]); + cl->do_oop((narrowOop*)_narrow[i]); + } + for (int j = i; j < _num_full; j++) { + cl->do_oop((oop*)_full[i]); + } + for (int j = i; j < _num_narrow; j++) { + cl->do_oop((narrowOop*)_narrow[i]); + } + } + + static const int MaxOrder = 2; + + void oops_do(OopClosure* cl, int do_oop_order) { + switch(do_oop_order) { + case 0: + oops_do_narrow_then_full(cl); + break; + case 1: + oops_do_full_then_narrow(cl); + break; + case 2: + oops_do_mixed(cl); + break; + default: + oops_do_narrow_then_full(cl); + break; + } + } + }; + + class CountOopClosure : public OopClosure { + int _narrow_oop_count; + int _full_oop_count; + public: + CountOopClosure() : _narrow_oop_count(0), _full_oop_count(0) {} + void do_oop(narrowOop* p) { + assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) != 0, + "The narrowOop was unexpectedly not marked with the NarrowOopMarker"); + _narrow_oop_count++; + } + + void do_oop(oop* p){ + assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) == 0, + "The oop was unexpectedly marked with the NarrowOopMarker"); + _full_oop_count++; + } + + int narrow_oop_count() { return _narrow_oop_count; } + int full_oop_count() { return _full_oop_count; } + int all_oop_count() { return _narrow_oop_count + _full_oop_count; } + }; + + class DoNothingOopClosure : public OopClosure { + public: + void do_oop(narrowOop* p) {} + void do_oop(oop* p) {} + }; + + static void testCount(int num_narrow, int num_full, int do_oop_order) { + FakeRoots fr(num_narrow, num_full); + + CountOopClosure coc; + BufferingOopClosure boc(&coc); + + fr.oops_do(&boc, do_oop_order); + + boc.done(); + + #define assert_testCount(got, expected) \ + assert((got) == (expected), \ + err_msg("Expected: %d, got: %d, when running testCount(%d, %d, %d)", \ + (got), (expected), num_narrow, num_full, do_oop_order)) + + assert_testCount(num_narrow, coc.narrow_oop_count()); + assert_testCount(num_full, coc.full_oop_count()); + assert_testCount(num_narrow + num_full, coc.all_oop_count()); + } + + static void testCount() { + int buffer_length = BufferingOopClosure::BufferLength; + + for (int order = 0; order < FakeRoots::MaxOrder; order++) { + testCount(0, 0, order); + testCount(10, 0, order); + testCount(0, 10, order); + testCount(10, 10, order); + testCount(buffer_length, 10, order); + testCount(10, buffer_length, order); + testCount(buffer_length, buffer_length, order); + testCount(buffer_length + 1, 10, order); + testCount(10, buffer_length + 1, order); + testCount(buffer_length + 1, buffer_length, order); + testCount(buffer_length, buffer_length + 1, order); + testCount(buffer_length + 1, buffer_length + 1, order); + } + } + + static void testIsBufferEmptyOrFull(int num_narrow, int num_full, bool expect_empty, bool expect_full) { + FakeRoots fr(num_narrow, num_full); + + DoNothingOopClosure cl; + BufferingOopClosure boc(&cl); + + fr.oops_do(&boc, 0); + + #define assert_testIsBufferEmptyOrFull(got, expected) \ + assert((got) == (expected), \ + err_msg("Expected: %d, got: %d. testIsBufferEmptyOrFull(%d, %d, %s, %s)", \ + (got), (expected), num_narrow, num_full, \ + BOOL_TO_STR(expect_empty), BOOL_TO_STR(expect_full))) + + assert_testIsBufferEmptyOrFull(expect_empty, boc.is_buffer_empty()); + assert_testIsBufferEmptyOrFull(expect_full, boc.is_buffer_full()); + } + + static void testIsBufferEmptyOrFull() { + int bl = BufferingOopClosure::BufferLength; + + testIsBufferEmptyOrFull(0, 0, true, false); + testIsBufferEmptyOrFull(1, 0, false, false); + testIsBufferEmptyOrFull(0, 1, false, false); + testIsBufferEmptyOrFull(1, 1, false, false); + testIsBufferEmptyOrFull(10, 0, false, false); + testIsBufferEmptyOrFull(0, 10, false, false); + testIsBufferEmptyOrFull(10, 10, false, false); + testIsBufferEmptyOrFull(0, bl, false, true); + testIsBufferEmptyOrFull(bl, 0, false, true); + testIsBufferEmptyOrFull(bl/2, bl/2, false, true); + testIsBufferEmptyOrFull(bl-1, 1, false, true); + testIsBufferEmptyOrFull(1, bl-1, false, true); + // Processed + testIsBufferEmptyOrFull(bl+1, 0, false, false); + testIsBufferEmptyOrFull(bl*2, 0, false, true); + } + + static void testEmptyAfterDone(int num_narrow, int num_full) { + FakeRoots fr(num_narrow, num_full); + + DoNothingOopClosure cl; + BufferingOopClosure boc(&cl); + + fr.oops_do(&boc, 0); + + // Make sure all get processed. + boc.done(); + + assert(boc.is_buffer_empty(), + err_msg("Should be empty after call to done(). testEmptyAfterDone(%d, %d)", + num_narrow, num_full)); + } + + static void testEmptyAfterDone() { + int bl = BufferingOopClosure::BufferLength; + + testEmptyAfterDone(0, 0); + testEmptyAfterDone(1, 0); + testEmptyAfterDone(0, 1); + testEmptyAfterDone(1, 1); + testEmptyAfterDone(10, 0); + testEmptyAfterDone(0, 10); + testEmptyAfterDone(10, 10); + testEmptyAfterDone(0, bl); + testEmptyAfterDone(bl, 0); + testEmptyAfterDone(bl/2, bl/2); + testEmptyAfterDone(bl-1, 1); + testEmptyAfterDone(1, bl-1); + // Processed + testEmptyAfterDone(bl+1, 0); + testEmptyAfterDone(bl*2, 0); + } + + public: + static void test() { + testCount(); + testIsBufferEmptyOrFull(); + testEmptyAfterDone(); + } +}; + +void TestBufferingOopClosure_test() { + TestBufferingOopClosure::test(); +} + +#endif diff --git a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp index 9d8d8704d33..ffdc69dfa5c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP -#include "memory/genOopClosures.hpp" -#include "memory/generation.hpp" +#include "memory/iterator.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/os.hpp" -#include "utilities/taskqueue.hpp" +#include "utilities/debug.hpp" // A BufferingOops closure tries to separate out the cost of finding roots // from the cost of applying closures to them. It maintains an array of @@ -41,60 +41,103 @@ // The caller must be sure to call "done" to process any unprocessed // buffered entries. -class Generation; -class HeapRegion; - class BufferingOopClosure: public OopClosure { + friend class TestBufferingOopClosure; protected: - enum PrivateConstants { - BufferLength = 1024 - }; + static const size_t BufferLength = 1024; - StarTask _buffer[BufferLength]; - StarTask* _buffer_top; - StarTask* _buffer_curr; + // We need to know if the buffered addresses contain oops or narrowOops. + // We can't tag the addresses the way StarTask does, because we need to + // be able to handle unaligned addresses coming from oops embedded in code. + // + // The addresses for the full-sized oops are filled in from the bottom, + // while the addresses for the narrowOops are filled in from the top. + OopOrNarrowOopStar _buffer[BufferLength]; + OopOrNarrowOopStar* _oop_top; + OopOrNarrowOopStar* _narrowOop_bottom; OopClosure* _oc; double _closure_app_seconds; - void process_buffer () { - double start = os::elapsedTime(); - for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) { - if (curr->is_narrow()) { - assert(UseCompressedOops, "Error"); - _oc->do_oop((narrowOop*)(*curr)); - } else { - _oc->do_oop((oop*)(*curr)); - } + + bool is_buffer_empty() { + return _oop_top == _buffer && _narrowOop_bottom == (_buffer + BufferLength - 1); + } + + bool is_buffer_full() { + return _narrowOop_bottom < _oop_top; + } + + // Process addresses containing full-sized oops. + void process_oops() { + for (OopOrNarrowOopStar* curr = _buffer; curr < _oop_top; ++curr) { + _oc->do_oop((oop*)(*curr)); } - _buffer_curr = _buffer; + _oop_top = _buffer; + } + + // Process addresses containing narrow oops. + void process_narrowOops() { + for (OopOrNarrowOopStar* curr = _buffer + BufferLength - 1; curr > _narrowOop_bottom; --curr) { + _oc->do_oop((narrowOop*)(*curr)); + } + _narrowOop_bottom = _buffer + BufferLength - 1; + } + + // Apply the closure to all oops and clear the buffer. + // Accumulate the time it took. + void process_buffer() { + double start = os::elapsedTime(); + + process_oops(); + process_narrowOops(); + _closure_app_seconds += (os::elapsedTime() - start); } - template inline void do_oop_work(T* p) { - if (_buffer_curr == _buffer_top) { + void process_buffer_if_full() { + if (is_buffer_full()) { process_buffer(); } - StarTask new_ref(p); - *_buffer_curr = new_ref; - ++_buffer_curr; + } + + void add_narrowOop(narrowOop* p) { + assert(!is_buffer_full(), "Buffer should not be full"); + *_narrowOop_bottom = (OopOrNarrowOopStar)p; + _narrowOop_bottom--; + } + + void add_oop(oop* p) { + assert(!is_buffer_full(), "Buffer should not be full"); + *_oop_top = (OopOrNarrowOopStar)p; + _oop_top++; } public: - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop(oop* p) { do_oop_work(p); } + virtual void do_oop(narrowOop* p) { + process_buffer_if_full(); + add_narrowOop(p); + } - void done () { - if (_buffer_curr > _buffer) { + virtual void do_oop(oop* p) { + process_buffer_if_full(); + add_oop(p); + } + + void done() { + if (!is_buffer_empty()) { process_buffer(); } } - double closure_app_seconds () { + + double closure_app_seconds() { return _closure_app_seconds; } - BufferingOopClosure (OopClosure *oc) : + + BufferingOopClosure(OopClosure *oc) : _oc(oc), - _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength), + _oop_top(_buffer), + _narrowOop_bottom(_buffer + BufferLength - 1), _closure_app_seconds(0.0) { } }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 44437fcdb7a..48e70a1c984 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" -#include "gc_implementation/g1/bufferingOopClosure.hpp" #include "gc_implementation/g1/concurrentG1Refine.hpp" #include "gc_implementation/g1/concurrentG1RefineThread.hpp" #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp" diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp index 7c010f9daf6..edaeff6e229 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index a4201f1e84b..c62c08b68cc 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -4952,6 +4952,7 @@ void TestVirtualSpaceNode_test(); void TestOldFreeSpaceCalculation_test(); #if INCLUDE_ALL_GCS void TestG1BiasedArray_test(); +void TestBufferingOopClosure_test(); #endif void execute_internal_vm_tests() { @@ -4977,6 +4978,7 @@ void execute_internal_vm_tests() { #if INCLUDE_ALL_GCS run_unit_test(TestG1BiasedArray_test()); run_unit_test(HeapRegionRemSet::test_prt()); + run_unit_test(TestBufferingOopClosure_test()); #endif tty->print_cr("All internal VM tests passed"); } From 5d460f1f3d9f1ac8a9cf64c5fc2b7a111e00fb9a Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 10 Feb 2014 12:58:09 +0100 Subject: [PATCH 056/265] 8033923: Use BufferingOopClosure for G1 code root scanning Reviewed-by: mgerdin, brutisso --- .../vm/gc_implementation/g1/g1CollectedHeap.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index a56b4ec0c23..f027f29491c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -5115,15 +5115,12 @@ g1_process_strong_roots(bool is_scavenging, BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); - assert(so & SO_AllCodeCache || scan_rs != NULL, "must scan code roots somehow"); - // Walk the code cache/strong code roots w/o buffering, because StarTask - // cannot handle unaligned oop locations. - CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, true /* do_marking */); + CodeBlobToOopClosure scan_code_roots(&buf_scan_non_heap_roots, true /* do_marking */); process_strong_roots(false, // no scoping; this is parallel code so, &buf_scan_non_heap_roots, - &eager_scan_code_roots, + &scan_code_roots, scan_klasses ); @@ -5177,9 +5174,9 @@ g1_process_strong_roots(bool is_scavenging, g1_policy()->phase_times()->record_strong_code_root_mark_time(worker_i, mark_strong_code_roots_ms); // Now scan the complement of the collection set. - if (scan_rs != NULL) { - g1_rem_set()->oops_into_collection_set_do(scan_rs, &eager_scan_code_roots, worker_i); - } + CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, true /* do_marking */); + g1_rem_set()->oops_into_collection_set_do(scan_rs, &eager_scan_code_roots, worker_i); + _process_strong_tasks->all_tasks_completed(); } From 40ba2bba2ccc3b5269481b29b1ee598bd248f253 Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Tue, 10 Dec 2013 15:11:02 +0100 Subject: [PATCH 057/265] 8026849: Fix typos in the GC code, part 2 Fixed typos in assert messages, flag descriptions and verbose messages Reviewed-by: stefank, tschatzl --- .../cmsAdaptiveSizePolicy.cpp | 2 +- .../concurrentMarkSweepGeneration.cpp | 6 +++--- .../concurrentMarkSweep/vmCMSOperations.cpp | 2 +- .../vm/gc_implementation/g1/g1_globals.hpp | 2 +- .../vm/gc_implementation/g1/satbQueue.cpp | 2 +- .../parNew/parCardTableModRefBS.cpp | 2 +- .../shared/adaptiveSizePolicy.cpp | 2 +- .../shared/mutableNUMASpace.cpp | 2 +- .../share/vm/memory/binaryTreeDictionary.cpp | 2 +- .../src/share/vm/memory/cardTableModRefBS.cpp | 4 ++-- hotspot/src/share/vm/memory/metaspace.cpp | 4 ++-- .../src/share/vm/memory/referenceProcessor.cpp | 2 +- hotspot/src/share/vm/runtime/globals.hpp | 18 +++++++----------- hotspot/src/share/vm/runtime/javaCalls.cpp | 2 +- hotspot/src/share/vm/runtime/os.cpp | 2 +- hotspot/src/share/vm/runtime/virtualspace.cpp | 4 ++-- 16 files changed, 27 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp index 999b1f8ca53..657ab30f5a6 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp @@ -700,7 +700,7 @@ void CMSAdaptiveSizePolicy::ms_collection_end(GCCause::Cause gc_cause) { double latest_cms_sum_concurrent_phases_time_secs = concurrent_collection_time(); if (PrintAdaptiveSizePolicy && Verbose) { - gclog_or_tty->print_cr("\nCMSAdaptiveSizePolicy::ms_collecton_end " + gclog_or_tty->print_cr("\nCMSAdaptiveSizePolicy::ms_collection_end " "STW_in_foreground_in_seconds %f " "_latest_cms_initial_mark_start_to_end_time_secs %f " "_latest_cms_remark_start_to_end_time_secs %f " diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index c6f608f5da6..847a8326fa0 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -958,7 +958,7 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() { desired_free_percentage); gclog_or_tty->print_cr(" Maximum free fraction %f", maximum_free_percentage); - gclog_or_tty->print_cr(" Capactiy "SIZE_FORMAT, capacity()/1000); + gclog_or_tty->print_cr(" Capacity "SIZE_FORMAT, capacity()/1000); gclog_or_tty->print_cr(" Desired capacity "SIZE_FORMAT, desired_capacity/1000); int prev_level = level() - 1; @@ -3313,7 +3313,7 @@ void CMSCollector::setup_cms_unloading_and_verification_state() { } // Not unloading classes this cycle - assert(!should_unload_classes(), "Inconsitency!"); + assert(!should_unload_classes(), "Inconsistency!"); remove_root_scanning_option(SharedHeap::SO_SystemClasses); add_root_scanning_option(SharedHeap::SO_AllClasses); @@ -7243,7 +7243,7 @@ size_t SurvivorSpacePrecleanClosure::do_object_careful(oop p) { HeapWord* addr = (HeapWord*)p; DEBUG_ONLY(_collector->verify_work_stacks_empty();) assert(!_span.contains(addr), "we are scanning the survivor spaces"); - assert(p->klass_or_null() != NULL, "object should be initializd"); + assert(p->klass_or_null() != NULL, "object should be initialized"); // an initialized object; ignore mark word in verification below // since we are running concurrent with mutators assert(p->is_oop(true), "should be an oop"); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp index 0860369e706..8024d298f05 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp @@ -254,7 +254,7 @@ bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const { // No need to do a young gc, we'll just nudge the CMS thread // in the doit() method above, to be executed soon. assert(_gc_count_before < gch->total_collections(), - "total_collections() should be monotnically increasing"); + "total_collections() should be monotonically increasing"); return false; // no need for foreground young gc } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index f82fda912c9..74158edb7c3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -183,7 +183,7 @@ "When true, record recent calls to rem set operations.") \ \ develop(intx, G1MaxVerifyFailures, -1, \ - "The maximum number of verification failrues to print. " \ + "The maximum number of verification failures to print. " \ "-1 means print all.") \ \ develop(bool, G1ScrubRemSets, true, \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp index ec6581431b3..3c34883a808 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp @@ -91,7 +91,7 @@ void ObjPtrQueue::filter() { assert(new_index > 0, "we should not have already filled up the buffer"); new_index -= oopSize; assert(new_index >= i, - "new_index should never be below i, as we alwaysr compact 'up'"); + "new_index should never be below i, as we always compact 'up'"); oop* new_p = (oop*) &buf[byte_index_to_index((int) new_index)]; assert(new_p >= p, "the destination location should never be below " "the source as we always compact 'up'"); diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp index 64bf6f03458..b1dacc870eb 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp @@ -250,7 +250,7 @@ process_chunk_boundaries(Space* sp, // right neighbor (up to the end of the first object). if (last_card_of_cur_chunk < last_card_of_first_obj) { tty->print_cr(" LNC: BEWARE!!! first obj straddles past right end of chunk:\n" - " might be efficient to get value from right neighbour?"); + " might be efficient to get value from right neighbor?"); } }) } else { diff --git a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp index ada9cbb3490..8c9ca0a9fd9 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp @@ -168,7 +168,7 @@ int AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers, if (TraceDynamicGCThreads) { gclog_or_tty->print_cr("GCTaskManager::calc_default_active_workers() : " - "active_workers(): %d new_acitve_workers: %d " + "active_workers(): %d new_active_workers: %d " "prev_active_workers: %d\n" " active_workers_by_JT: %d active_workers_by_heap_size: %d", active_workers, new_active_workers, prev_active_workers, diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index f27cf5155d0..e198590ef4b 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -559,7 +559,7 @@ void MutableNUMASpace::initialize(MemRegion mr, bool clear_space, bool mangle_space, bool setup_pages) { - assert(clear_space, "Reallocation will destory data!"); + assert(clear_space, "Reallocation will destroy data!"); assert(lgrp_spaces()->length() > 0, "There should be at least one space"); MemRegion old_region = region(), new_region; diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 9f2dcebfc14..68b97e9f0d3 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -1352,7 +1352,7 @@ void BinaryTreeDictionary::print_free_lists(outputStream* s template class FreeList_t> void BinaryTreeDictionary::verify_tree() const { guarantee(root() == NULL || total_free_blocks() == 0 || - total_size() != 0, "_total_size should't be 0?"); + total_size() != 0, "_total_size shouldn't be 0?"); guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent"); verify_tree_helper(root()); } diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index 2f23b3a7617..76c899e973d 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -54,8 +54,8 @@ size_t CardTableModRefBS::cards_required(size_t covered_words) size_t CardTableModRefBS::compute_byte_map_size() { assert(_guard_index == cards_required(_whole_heap.word_size()) - 1, - "unitialized, check declaration order"); - assert(_page_size != 0, "unitialized, check declaration order"); + "uninitialized, check declaration order"); + assert(_page_size != 0, "uninitialized, check declaration order"); const size_t granularity = os::vm_allocation_granularity(); return align_size_up(_guard_index + 1, MAX2(_page_size, granularity)); } diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 73da1c74ef8..6105321c30f 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -746,7 +746,7 @@ void VirtualSpaceNode::inc_container_count() { assert_lock_strong(SpaceManager::expand_lock()); _container_count++; assert(_container_count == container_count_slow(), - err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT + err_msg("Inconsistency in container_count _container_count " SIZE_FORMAT " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); } @@ -759,7 +759,7 @@ void VirtualSpaceNode::dec_container_count() { #ifdef ASSERT void VirtualSpaceNode::verify_container_count() { assert(_container_count == container_count_slow(), - err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT + err_msg("Inconsistency in container_count _container_count " SIZE_FORMAT " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); } #endif diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index d7d48ba7548..72a43d85df3 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -62,7 +62,7 @@ void ReferenceProcessor::init_statics() { } guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || RefDiscoveryPolicy == ReferentBasedDiscovery, - "Unrecongnized RefDiscoveryPolicy"); + "Unrecognized RefDiscoveryPolicy"); _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index b5d8880e91e..eb3a01bebac 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -565,7 +565,7 @@ class CommandLineFlags { "Force NUMA optimizations on single-node/UMA systems") \ \ product(uintx, NUMAChunkResizeWeight, 20, \ - "Percentage (0-100) used to weigh the current sample when " \ + "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying average for " \ "AdaptiveNUMAChunkSizing") \ \ @@ -1502,7 +1502,7 @@ class CommandLineFlags { "allocation") \ \ product(uintx, PLABWeight, 75, \ - "Percentage (0-100) used to weigh the current sample when " \ + "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying average for ResizePLAB") \ \ product(bool, ResizePLAB, true, \ @@ -1611,11 +1611,11 @@ class CommandLineFlags { "is shifted to the right within the period between young GCs") \ \ product(uintx, CMSExpAvgFactor, 50, \ - "Percentage (0-100) used to weigh the current sample when " \ + "Percentage (0-100) used to weight the current sample when " \ "computing exponential averages for CMS statistics") \ \ product(uintx, CMS_FLSWeight, 75, \ - "Percentage (0-100) used to weigh the current sample when " \ + "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying averages for CMS FLS " \ "statistics") \ \ @@ -1727,19 +1727,15 @@ class CommandLineFlags { "to simulate overflow; a smaller number increases frequency") \ \ product(uintx, CMSMaxAbortablePrecleanLoops, 0, \ - "(Temporary, subject to experimentation) " \ "Maximum number of abortable preclean iterations, if > 0") \ \ product(intx, CMSMaxAbortablePrecleanTime, 5000, \ - "(Temporary, subject to experimentation) " \ "Maximum time in abortable preclean (in milliseconds)") \ \ product(uintx, CMSAbortablePrecleanMinWorkPerIteration, 100, \ - "(Temporary, subject to experimentation) " \ "Nominal minimum work per abortable preclean iteration") \ \ manageable(intx, CMSAbortablePrecleanWaitMillis, 100, \ - "(Temporary, subject to experimentation) " \ "Time that we sleep between iterations when not given " \ "enough work per iteration") \ \ @@ -1955,13 +1951,13 @@ class CommandLineFlags { "(other young collectors)") \ \ develop(uintx, PromotionFailureALotInterval, 5, \ - "Total collections between promotion failures alot") \ + "Total collections between promotion failures a lot") \ \ experimental(uintx, WorkStealingSleepMillis, 1, \ "Sleep time when sleep is used for yields") \ \ experimental(uintx, WorkStealingYieldsBeforeSleep, 5000, \ - "Number of yields before a sleep is done during workstealing") \ + "Number of yields before a sleep is done during work stealing") \ \ experimental(uintx, WorkStealingHardSpins, 4096, \ "Number of iterations in a spin loop between checks on " \ @@ -2039,7 +2035,7 @@ class CommandLineFlags { "size; deprecated: to be renamed to MaxRAMFraction") \ \ product(uintx, MinRAMFraction, 2, \ - "Minimum fraction (1/n) of real memory used for maxmimum heap " \ + "Minimum fraction (1/n) of real memory used for maximum heap " \ "size on systems with small physical memory size") \ \ product(uintx, InitialRAMFraction, 64, \ diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index 027d8d9b50f..d7ff466ec36 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -337,7 +337,7 @@ void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArgument // A klass might not be initialized since JavaCall's might be used during the executing of // the . For example, a Thread.start might start executing on an object that is // not fully initialized! (bad Java programming style) - assert(holder->is_linked(), "rewritting must have taken place"); + assert(holder->is_linked(), "rewriting must have taken place"); } #endif diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 74617ab97e8..3062861360f 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1197,7 +1197,7 @@ char* os::format_boot_path(const char* format_string, char fileSep, char pathSep) { assert((fileSep == '/' && pathSep == ':') || - (fileSep == '\\' && pathSep == ';'), "unexpected seperator chars"); + (fileSep == '\\' && pathSep == ';'), "unexpected separator chars"); // Scan the format string to determine the length of the actual // boot classpath, and handle platform dependencies as well. diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index 45730fa49fc..0e14c57e26c 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -215,9 +215,9 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, noaccess_prefix == _alignment, "noaccess prefix wrong"); assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base, - "area must be distinguisable from marks for mark-sweep"); + "area must be distinguishable from marks for mark-sweep"); assert(markOopDesc::encode_pointer_as_mark(&_base[size])->decode_pointer() == &_base[size], - "area must be distinguisable from marks for mark-sweep"); + "area must be distinguishable from marks for mark-sweep"); } From 7d5651867132e5248f33af20ae80cfae6852e483 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 11 Dec 2013 00:06:11 +0100 Subject: [PATCH 058/265] 8029940: PPC64 (part 122): C2 compiler port Reviewed-by: kvn --- hotspot/make/aix/makefiles/adlc.make | 6 +- hotspot/src/cpu/ppc/vm/assembler_ppc.hpp | 80 +- .../src/cpu/ppc/vm/assembler_ppc.inline.hpp | 35 +- .../cpu/ppc/vm/bytecodeInterpreter_ppc.hpp | 1 + hotspot/src/cpu/ppc/vm/bytes_ppc.hpp | 3 +- hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp | 98 + hotspot/src/cpu/ppc/vm/c2_init_ppc.cpp | 48 + hotspot/src/cpu/ppc/vm/copy_ppc.hpp | 4 + hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp | 3 +- hotspot/src/cpu/ppc/vm/frame_ppc.cpp | 6 +- hotspot/src/cpu/ppc/vm/frame_ppc.hpp | 3 +- hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp | 7 +- hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 16 +- hotspot/src/cpu/ppc/vm/icache_ppc.cpp | 32 +- hotspot/src/cpu/ppc/vm/icache_ppc.hpp | 18 +- hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp | 72 +- hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp | 8 +- hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp | 197 +- hotspot/src/cpu/ppc/vm/jni_ppc.h | 6 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 120 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp | 29 +- .../cpu/ppc/vm/macroAssembler_ppc.inline.hpp | 48 +- hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp | 25 +- hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp | 57 +- hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 7 +- hotspot/src/cpu/ppc/vm/ppc.ad | 12059 ++++++++++++++++ hotspot/src/cpu/ppc/vm/ppc_64.ad | 24 + .../cpu/ppc/vm/register_definitions_ppc.cpp | 4 +- hotspot/src/cpu/ppc/vm/register_ppc.cpp | 4 +- hotspot/src/cpu/ppc/vm/register_ppc.hpp | 10 +- hotspot/src/cpu/ppc/vm/runtime_ppc.cpp | 183 + hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 127 +- hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 139 +- hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 100 +- hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 4 +- .../aix_ppc/vm/orderAccess_aix_ppc.inline.hpp | 172 +- hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp | 29 +- .../linux_ppc/vm/atomic_linux_ppc.inline.hpp | 40 +- .../vm/orderAccess_linux_ppc.inline.hpp | 22 +- .../src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp | 21 +- 40 files changed, 13274 insertions(+), 593 deletions(-) create mode 100644 hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp create mode 100644 hotspot/src/cpu/ppc/vm/c2_init_ppc.cpp create mode 100644 hotspot/src/cpu/ppc/vm/ppc.ad create mode 100644 hotspot/src/cpu/ppc/vm/ppc_64.ad create mode 100644 hotspot/src/cpu/ppc/vm/runtime_ppc.cpp diff --git a/hotspot/make/aix/makefiles/adlc.make b/hotspot/make/aix/makefiles/adlc.make index d104860b432..4355d73b7b9 100644 --- a/hotspot/make/aix/makefiles/adlc.make +++ b/hotspot/make/aix/makefiles/adlc.make @@ -41,13 +41,11 @@ SOURCE.AD = $(OUTDIR)/$(OS)_$(Platform_arch_model).ad ifeq ("${Platform_arch_model}", "${Platform_arch}") SOURCES.AD = \ - $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \ - $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad) + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) else SOURCES.AD = \ $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \ - $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch).ad) \ - $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad) + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch).ad) endif EXEC = $(OUTDIR)/adlc diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index 896ea3c1954..b0519a63b08 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -98,7 +98,17 @@ class Argument VALUE_OBJ_CLASS_SPEC { // Only 8 registers may contain integer parameters. n_register_parameters = 8, // Can have up to 8 floating registers. - n_float_register_parameters = 8 + n_float_register_parameters = 8, + + // PPC C calling conventions. + // The first eight arguments are passed in int regs if they are int. + n_int_register_parameters_c = 8, + // The first thirteen float arguments are passed in float regs. + n_float_register_parameters_c = 13, + // Only the first 8 parameters are not placed on the stack. Aix disassembly + // shows that xlC places all float args after argument 8 on the stack AND + // in a register. This is not documented, but we follow this convention, too. + n_regs_not_on_stack_c = 8, }; // creation Argument(int number) : _number(number) {} @@ -662,6 +672,14 @@ class Assembler : public AbstractAssembler { bcondCRbiIs1_bhintIsTaken = bcondCRbiIs1 | bhintatIsTaken, }; + // Elemental Memory Barriers (>=Power 8) + enum Elemental_Membar_mask_bits { + StoreStore = 1 << 0, + StoreLoad = 1 << 1, + LoadStore = 1 << 2, + LoadLoad = 1 << 3 + }; + // Branch prediction hints. inline static int add_bhint_to_boint(const int bhint, const int boint) { switch (boint) { @@ -753,17 +771,6 @@ class Assembler : public AbstractAssembler { enum Predict { pt = 1, pn = 0 }; // pt = predict taken - enum Membar_mask_bits { // page 184, v9 - StoreStore = 1 << 3, - LoadStore = 1 << 2, - StoreLoad = 1 << 1, - LoadLoad = 1 << 0, - - Sync = 1 << 6, - MemIssue = 1 << 5, - Lookaside = 1 << 4 - }; - // instruction must start at passed address static int instr_len(unsigned char *instr) { return BytesPerInstWord; } @@ -875,19 +882,20 @@ class Assembler : public AbstractAssembler { #define inv_opp_s_field(x, hi_bit, lo_bit) inv_s_field_ppc(x, 31-(lo_bit), 31-(hi_bit)) // Extract instruction fields from instruction words. public: - static int inv_ra_field(int x) { return inv_opp_u_field(x, 15, 11); } - static int inv_rb_field(int x) { return inv_opp_u_field(x, 20, 16); } - static int inv_rt_field(int x) { return inv_opp_u_field(x, 10, 6); } - static int inv_rs_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_ra_field(int x) { return inv_opp_u_field(x, 15, 11); } + static int inv_rb_field(int x) { return inv_opp_u_field(x, 20, 16); } + static int inv_rt_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_rta_field(int x) { return inv_opp_u_field(x, 15, 11); } + static int inv_rs_field(int x) { return inv_opp_u_field(x, 10, 6); } // Ds uses opp_s_field(x, 31, 16), but lowest 2 bits must be 0. // Inv_ds_field uses range (x, 29, 16) but shifts by 2 to ensure that lowest bits are 0. - static int inv_ds_field(int x) { return inv_opp_s_field(x, 29, 16) << 2; } - static int inv_d1_field(int x) { return inv_opp_s_field(x, 31, 16); } - static int inv_si_field(int x) { return inv_opp_s_field(x, 31, 16); } - static int inv_to_field(int x) { return inv_opp_u_field(x, 10, 6); } - static int inv_lk_field(int x) { return inv_opp_u_field(x, 31, 31); } - static int inv_bo_field(int x) { return inv_opp_u_field(x, 10, 6); } - static int inv_bi_field(int x) { return inv_opp_u_field(x, 15, 11); } + static int inv_ds_field(int x) { return inv_opp_s_field(x, 29, 16) << 2; } + static int inv_d1_field(int x) { return inv_opp_s_field(x, 31, 16); } + static int inv_si_field(int x) { return inv_opp_s_field(x, 31, 16); } + static int inv_to_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_lk_field(int x) { return inv_opp_u_field(x, 31, 31); } + static int inv_bo_field(int x) { return inv_opp_u_field(x, 10, 6); } + static int inv_bi_field(int x) { return inv_opp_u_field(x, 15, 11); } #define opp_u_field(x, hi_bit, lo_bit) u_field(x, 31-(lo_bit), 31-(hi_bit)) #define opp_s_field(x, hi_bit, lo_bit) s_field(x, 31-(lo_bit), 31-(hi_bit)) @@ -925,6 +933,7 @@ class Assembler : public AbstractAssembler { static int l10( int x) { return opp_u_field(x, 10, 10); } static int l15( int x) { return opp_u_field(x, 15, 15); } static int l910( int x) { return opp_u_field(x, 10, 9); } + static int e1215( int x) { return opp_u_field(x, 15, 12); } static int lev( int x) { return opp_u_field(x, 26, 20); } static int li( int x) { return opp_s_field(x, 29, 6); } static int lk( int x) { return opp_u_field(x, 31, 31); } @@ -960,13 +969,13 @@ class Assembler : public AbstractAssembler { static int sr( int x) { return opp_u_field(x, 15, 12); } static int tbr( int x) { return opp_u_field(x, 20, 11); } static int th( int x) { return opp_u_field(x, 10, 7); } - static int thct( int x) { assert((x&8)==0, "must be valid cache specification"); return th(x); } - static int thds( int x) { assert((x&8)==8, "must be valid stream specification"); return th(x); } + static int thct( int x) { assert((x&8) == 0, "must be valid cache specification"); return th(x); } + static int thds( int x) { assert((x&8) == 8, "must be valid stream specification"); return th(x); } static int to( int x) { return opp_u_field(x, 10, 6); } static int u( int x) { return opp_u_field(x, 19, 16); } static int ui( int x) { return opp_u_field(x, 31, 16); } - // support vector instructions for >= Power6 + // Support vector instructions for >= Power6. static int vra( int x) { return opp_u_field(x, 15, 11); } static int vrb( int x) { return opp_u_field(x, 20, 16); } static int vrc( int x) { return opp_u_field(x, 25, 21); } @@ -1090,8 +1099,8 @@ class Assembler : public AbstractAssembler { inline void subfic( Register d, Register a, int si16); inline void add( Register d, Register a, Register b); inline void add_( Register d, Register a, Register b); - inline void subf( Register d, Register a, Register b); - inline void sub( Register d, Register a, Register b); + inline void subf( Register d, Register a, Register b); // d = b - a "Sub_from", as in ppc spec. + inline void sub( Register d, Register a, Register b); // d = a - b Swap operands of subf for readability. inline void subf_( Register d, Register a, Register b); inline void addc( Register d, Register a, Register b); inline void addc_( Register d, Register a, Register b); @@ -1204,7 +1213,7 @@ class Assembler : public AbstractAssembler { } // endgroup opcode for Power6 static bool is_endgroup(int x) { - return is_ori(x) && inv_ra_field(x)==1 && inv_rs_field(x)==1 && inv_d1_field(x)==0; + return is_ori(x) && inv_ra_field(x) == 1 && inv_rs_field(x) == 1 && inv_d1_field(x) == 0; } @@ -1227,9 +1236,13 @@ class Assembler : public AbstractAssembler { inline void cmpld( ConditionRegister crx, Register a, Register b); inline void isel( Register d, Register a, Register b, int bc); + // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value. + inline void isel( Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg); + // Set d = 0 if (cr.cc) equals 1, otherwise b. + inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg); // PPC 1, section 3.3.11, Fixed-Point Logical Instructions - void andi( Register a, Register s, int ui16); // optimized version + void andi( Register a, Register s, int ui16); // optimized version inline void andi_( Register a, Register s, int ui16); inline void andis_( Register a, Register s, int ui16); inline void ori( Register a, Register s, int ui16); @@ -1553,10 +1566,7 @@ class Assembler : public AbstractAssembler { inline void ptesync(); inline void eieio(); inline void isync(); - - inline void release(); - inline void acquire(); - inline void fence(); + inline void elemental_membar(int e); // Elemental Memory Barriers (>=Power 8) // atomics inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0); @@ -1938,7 +1948,7 @@ class Assembler : public AbstractAssembler { inline void load_const(Register d, AddressLiteral& a, Register tmp = noreg); // Load a 64 bit constant, optimized, not identifyable. - // Tmp can be used to increase ILP. Set return_simm16_rest=true to get a + // Tmp can be used to increase ILP. Set return_simm16_rest = true to get a // 16 bit immediate offset. This is useful if the offset can be encoded in // a succeeding instruction. int load_const_optimized(Register d, long a, Register tmp = noreg, bool return_simm16_rest = false); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index a1277b8cdbb..200aaf11aed 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -224,8 +224,12 @@ inline void Assembler::clrlsldi_(Register a, Register s, int clrl6, int shl6) { inline void Assembler::extrdi( Register a, Register s, int n, int b){ Assembler::rldicl(a, s, b+n, 64-n); } // testbit with condition register. inline void Assembler::testbitdi(ConditionRegister cr, Register a, Register s, int ui6) { - Assembler::rldicr(a, s, 63-ui6, 0); - Assembler::cmpdi(cr, a, 0); + if (cr == CCR0) { + Assembler::rldicr_(a, s, 63-ui6, 0); + } else { + Assembler::rldicr(a, s, 63-ui6, 0); + Assembler::cmpdi(cr, a, 0); + } } // rotate instructions @@ -423,6 +427,27 @@ inline void Assembler::creqv( int d, int s1, int s2) { emit_int32(CREQV_OPCODE inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); } inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE | bt(d) | ba(s1) | bb(s2)); } +// Conditional move (>= Power7) +inline void Assembler::isel(Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b) { + if (b == noreg) { + b = d; // Can be omitted if old value should be kept in "else" case. + } + Register first = a; + Register second = b; + if (inv) { + first = b; + second = a; // exchange + } + assert(first != R0, "r0 not allowed"); + isel(d, first, second, bi0(cr, cc)); +} +inline void Assembler::isel_0(Register d, ConditionRegister cr, Condition cc, Register b) { + if (b == noreg) { + b = d; // Can be omitted if old value should be kept in "else" case. + } + isel(d, R0, b, bi0(cr, cc)); +} + // PPC 2, section 3.2.1 Instruction Cache Instructions inline void Assembler::icbi( Register s1, Register s2) { emit_int32( ICBI_OPCODE | ra0mem(s1) | rb(s2) ); } // PPC 2, section 3.2.2 Data Cache Instructions @@ -445,10 +470,7 @@ inline void Assembler::lwsync() { Assembler::sync(1); } inline void Assembler::ptesync() { Assembler::sync(2); } inline void Assembler::eieio() { emit_int32( EIEIO_OPCODE); } inline void Assembler::isync() { emit_int32( ISYNC_OPCODE); } - -inline void Assembler::release() { Assembler::lwsync(); } -inline void Assembler::acquire() { Assembler::lwsync(); } -inline void Assembler::fence() { Assembler::sync(); } +inline void Assembler::elemental_membar(int e) { assert(0 < e && e < 16, "invalid encoding"); emit_int32( SYNC_OPCODE | e1215(e)); } // atomics // Use ra0mem to disallow R0 as base. @@ -767,7 +789,6 @@ inline void Assembler::stvxl( VectorRegister d, Register s2) { emit_int32( STVXL inline void Assembler::lvsl( VectorRegister d, Register s2) { emit_int32( LVSL_OPCODE | vrt(d) | rb(s2)); } inline void Assembler::lvsr( VectorRegister d, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | rb(s2)); } - inline void Assembler::load_const(Register d, void* x, Register tmp) { load_const(d, (long)x, tmp); } diff --git a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp index 038854f6d2c..5b834e55cba 100644 --- a/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/bytecodeInterpreter_ppc.hpp @@ -100,6 +100,7 @@ public: #define SET_LOCALS_DOUBLE(value, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->d = (value)) #define SET_LOCALS_LONG(value, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->l = (value)) #define SET_LOCALS_DOUBLE_FROM_ADDR(addr, offset) (((VMJavaVal64*)&locals[-((offset)+1)])->d = \ + ((VMJavaVal64*)(addr))->d) #endif // CPU_PPC_VM_BYTECODEINTERPRETER_PPC_PP diff --git a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp index 507793037dc..872aa6b2624 100644 --- a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp @@ -33,7 +33,7 @@ class Bytes: AllStatic { // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering // PowerPC needs to check for alignment. - // can I count on address always being a pointer to an unsigned char? Yes + // Can I count on address always being a pointer to an unsigned char? Yes. // Returns true, if the byte ordering used by Java is different from the nativ byte ordering // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. @@ -141,7 +141,6 @@ class Bytes: AllStatic { } } - // Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering) // (no byte-order reversal is needed since Power CPUs are big-endian oriented). static inline u2 get_Java_u2(address p) { return get_native_u2(p); } diff --git a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp new file mode 100644 index 00000000000..03e5a5d0b55 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 CPU_PPC_VM_C2_GLOBALS_PPC_HPP +#define CPU_PPC_VM_C2_GLOBALS_PPC_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the server compiler. +// (see c2_globals.hpp). + +define_pd_global(bool, BackgroundCompilation, true); +define_pd_global(bool, CICompileOSR, true); +define_pd_global(bool, InlineIntrinsics, true); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, true); +define_pd_global(bool, UseOnStackReplacement, true); +define_pd_global(bool, ProfileInterpreter, true); +define_pd_global(bool, TieredCompilation, false); +define_pd_global(intx, CompileThreshold, 10000); +define_pd_global(intx, BackEdgeThreshold, 140000); + +define_pd_global(intx, OnStackReplacePercentage, 140); +define_pd_global(intx, ConditionalMoveLimit, 3); +define_pd_global(intx, FLOATPRESSURE, 28); +define_pd_global(intx, FreqInlineSize, 175); +define_pd_global(intx, MinJumpTableSize, 10); +define_pd_global(intx, INTPRESSURE, 25); +define_pd_global(intx, InteriorEntryAlignment, 16); +define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); +define_pd_global(intx, RegisterCostAreaRatio, 16000); +define_pd_global(bool, UseTLAB, true); +define_pd_global(bool, ResizeTLAB, true); +define_pd_global(intx, LoopUnrollLimit, 60); + +// Peephole and CISC spilling both break the graph, and so make the +// scheduler sick. +define_pd_global(bool, OptoPeephole, false); +define_pd_global(bool, UseCISCSpill, false); +define_pd_global(bool, OptoBundling, false); +// GL: +// Detected a problem with unscaled compressed oops and +// narrow_oop_use_complex_address() == false. +// -Djava.io.tmpdir=./tmp -jar SPECjvm2008.jar -ikv -wt 3 -it 3 +// -bt 1 --base compiler.sunflow +// fails in Lower.visitIf->translate->tranlate->translate and +// throws an unexpected NPE. A load and a store seem to be +// reordered. Java reads about: +// loc = x.f +// x.f = 0 +// NullCheck loc +// While assembler reads: +// x.f = 0 +// loc = x.f +// NullCheck loc +define_pd_global(bool, OptoScheduling, false); + +define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(intx, ReservedCodeCacheSize, 256*M); +define_pd_global(intx, CodeCacheExpansionSize, 64*K); + +// Ergonomics related flags +define_pd_global(uint64_t,MaxRAM, 4ULL*G); +define_pd_global(uintx, CodeCacheMinBlockLength, 4); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); + +define_pd_global(bool, TrapBasedRangeChecks, false); + +// Heap related flags +define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); + +// Ergonomics related flags +define_pd_global(bool, NeverActAsServerClassMachine, false); + +#endif // CPU_PPC_VM_C2_GLOBALS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/c2_init_ppc.cpp b/hotspot/src/cpu/ppc/vm/c2_init_ppc.cpp new file mode 100644 index 00000000000..94b59db4d7e --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/c2_init_ppc.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "opto/compile.hpp" +#include "opto/node.hpp" +#include "runtime/globals.hpp" +#include "utilities/debug.hpp" + +// processor dependent initialization for ppc + +void Compile::pd_compiler2_init() { + + // Power7 and later + if (PowerArchitecturePPC64 > 6) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_ERGO(bool, UsePopCountInstruction, true); + } + } + + if (PowerArchitecturePPC64 == 6) { + if (FLAG_IS_DEFAULT(InsertEndGroupPPC64)) { + FLAG_SET_ERGO(bool, InsertEndGroupPPC64, true); + } + } +} diff --git a/hotspot/src/cpu/ppc/vm/copy_ppc.hpp b/hotspot/src/cpu/ppc/vm/copy_ppc.hpp index 61937be3e86..0094c0c6d30 100644 --- a/hotspot/src/cpu/ppc/vm/copy_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/copy_ppc.hpp @@ -105,10 +105,12 @@ static void copy_conjoint_atomic(T* from, T* to, size_t count) { } static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { + // TODO: contribute optimized version. copy_conjoint_atomic(from, to, count); } static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { + // TODO: contribute optimized version. copy_conjoint_atomic(from, to, count); } @@ -125,10 +127,12 @@ static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count } static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) { + // TODO: contribute optimized version. pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count); } static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) { + // TODO: contribute optimized version. pd_conjoint_jints_atomic((jint*)from, (jint*)to, count); } diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp index aaadf69fc93..3095ccd98b6 100644 --- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp @@ -1981,8 +1981,7 @@ address CppInterpreterGenerator::generate_normal_entry(void) { // Restore R14_state. __ ld(R14_state, 0, R1_SP); - __ addi(R14_state, R14_state, - -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + __ addi(R14_state, R14_state, -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); // // Registers alive diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp index 2800635adf8..1cd2c6a0a5b 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp @@ -176,13 +176,14 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) Method* method = interpreter_frame_method(); BasicType type = method->result_type(); -#ifdef CC_INTERP if (method->is_native()) { // Prior to calling into the runtime to notify the method exit the possible // result value is saved into the interpreter frame. +#ifdef CC_INTERP interpreterState istate = get_interpreterState(); address lresult = (address)istate + in_bytes(BytecodeInterpreter::native_lresult_offset()); address fresult = (address)istate + in_bytes(BytecodeInterpreter::native_fresult_offset()); +#endif switch (method->result_type()) { case T_OBJECT: @@ -226,9 +227,6 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) default : ShouldNotReachHere(); } } -#else - Unimplemented(); -#endif return type; } diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp index 73c216e4c82..26321baeb89 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -421,7 +421,7 @@ #ifdef CC_INTERP // Additional interface for interpreter frames: inline interpreterState get_interpreterState() const; -#endif +#endif // CC_INTERP // Size of a monitor in bytes. static int interpreter_frame_monitor_size_in_bytes(); @@ -431,7 +431,6 @@ private: - // PPC port: permgen stuff ConstantPoolCache** interpreter_frame_cpoolcache_addr() const; public: diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp index bb908225155..2dadd6c69eb 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp @@ -78,11 +78,8 @@ inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp) // can distinguish identity and younger/older relationship. NULL // represents an invalid (incomparable) frame. inline intptr_t* frame::id(void) const { - // Use the _unextended_pc as the frame's ID. Because we have no - // adapters, but resized compiled frames, some of the new code - // (e.g. JVMTI) wouldn't work if we return the (current) SP of the - // frame. - return _unextended_sp; + // Use _fp. _sp or _unextended_sp wouldn't be correct due to resizing. + return _fp; } // Return true if this frame is older (less recent activation) than diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index 1e3c327765f..36bdf7325a5 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -62,6 +62,13 @@ define_pd_global(uintx, TypeProfileLevel, 0); // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ + \ + /* Load poll address from thread. This is used to implement per-thread */ \ + /* safepoints on platforms != IA64. */ \ + product(bool, LoadPollAddressFromThread, false, \ + "Load polling page address from thread object (required for " \ + "per-thread safepoints on platforms != IA64)") \ + \ product(uintx, PowerArchitecturePPC64, 0, \ "CPU Version: x for PowerX. Currently recognizes Power5 to " \ "Power7. Default is 0. CPUs newer than Power7 will be " \ @@ -88,6 +95,14 @@ define_pd_global(uintx, TypeProfileLevel, 0); \ product(bool, UseStaticBranchPredictionInCompareAndSwapPPC64, true, \ "Use static branch prediction hints in CAS operations.") \ + 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 */ \ @@ -108,5 +123,4 @@ define_pd_global(uintx, TypeProfileLevel, 0); " Use this to ease debugging.") \ - #endif // CPU_PPC_VM_GLOBALS_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/icache_ppc.cpp b/hotspot/src/cpu/ppc/vm/icache_ppc.cpp index 386e00dbd9f..20b11455bf6 100644 --- a/hotspot/src/cpu/ppc/vm/icache_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/icache_ppc.cpp @@ -28,17 +28,17 @@ #include "runtime/icache.hpp" // Use inline assembler to implement icache flush. -int ppc64_flush_icache(address start, int lines, int magic){ +int ICache::ppc64_flush_icache(address start, int lines, int magic) { address end = start + (unsigned int)lines*ICache::line_size; assert(start <= end, "flush_icache parms"); // store modified cache lines from data cache - for (address a=start; a> log2_line_size, 0); + } }; #endif // CPU_PPC_VM_ICACHE_PPC_HPP diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index b9886b82126..5d135199b7e 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -30,13 +30,21 @@ #include "interp_masm_ppc_64.hpp" #include "interpreter/interpreterRuntime.hpp" - #ifdef PRODUCT #define BLOCK_COMMENT(str) // nothing #else #define BLOCK_COMMENT(str) block_comment(str) #endif +void InterpreterMacroAssembler::null_check_throw(Register a, int offset, Register temp_reg) { +#ifdef CC_INTERP + address exception_entry = StubRoutines::throw_NullPointerException_at_call_entry(); +#else + address exception_entry = Interpreter::throw_NullPointerException_entry(); +#endif + MacroAssembler::null_check_throw(a, offset, temp_reg, exception_entry); +} + // Lock object // // Registers alive @@ -47,7 +55,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { if (UseHeavyMonitors) { call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), - monitor, /*check_for_exceptions=*/false); + monitor, /*check_for_exceptions=*/true CC_INTERP_ONLY(&& false)); } else { // template code: // @@ -69,7 +77,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { const Register tmp = R10_ARG8; Label done; - Label slow_case; + Label cas_failed, slow_case; assert_different_registers(displaced_header, object_mark_addr, current_header, tmp); @@ -91,7 +99,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { // Initialize the box (Must happen before we update the object mark!). std(displaced_header, BasicObjectLock::lock_offset_in_bytes() + - BasicLock::displaced_header_offset_in_bytes(), monitor); + BasicLock::displaced_header_offset_in_bytes(), monitor); // if (Atomic::cmpxchg_ptr(/*ex=*/monitor, /*addr*/obj->mark_addr(), /*cmp*/displaced_header) == displaced_header) { @@ -106,12 +114,14 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { /*compare_value=*/displaced_header, /*exchange_value=*/monitor, /*where=*/object_mark_addr, MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, - MacroAssembler::cmpxchgx_hint_acquire_lock()); + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, + &cas_failed); // If the compare-and-exchange succeeded, then we found an unlocked // object and we have now locked it. - beq(CCR0, done); - + b(done); + bind(cas_failed); // } else if (THREAD->is_lock_owned((address)displaced_header)) // // Simple recursive case. @@ -134,7 +144,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { bne(CCR0, slow_case); release(); std(R0/*==0!*/, BasicObjectLock::lock_offset_in_bytes() + - BasicLock::displaced_header_offset_in_bytes(), monitor); + BasicLock::displaced_header_offset_in_bytes(), monitor); b(done); @@ -146,7 +156,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { // slow case of monitor enter. bind(slow_case); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), - monitor, /*check_for_exceptions=*/false); + monitor, /*check_for_exceptions=*/true CC_INTERP_ONLY(&& false)); // } bind(done); @@ -160,7 +170,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) { // which must be initialized with the object to lock. // // Throw IllegalMonitorException if object is not locked by current thread. -void InterpreterMacroAssembler::unlock_object(Register monitor) { +void InterpreterMacroAssembler::unlock_object(Register monitor, bool check_for_exceptions) { if (UseHeavyMonitors) { call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor, /*check_for_exceptions=*/false); @@ -184,9 +194,8 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { const Register object_mark_addr = R9_ARG7; const Register current_header = R10_ARG8; - Label no_recursive_unlock; + Label free_slot; Label slow_case; - Label done; assert_different_registers(object, displaced_header, object_mark_addr, current_header); @@ -194,7 +203,7 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { // The object address from the monitor is in object. ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); - biased_locking_exit(CCR0, object, displaced_header, done); + biased_locking_exit(CCR0, object, displaced_header, free_slot); } // Test first if we are in the fast recursive case. @@ -203,13 +212,7 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { // If the displaced header is zero, we have a recursive unlock. cmpdi(CCR0, displaced_header, 0); - bne(CCR0, no_recursive_unlock); - // Release in recursive unlock is not necessary. - // release(); - std(displaced_header/*==0!*/, BasicObjectLock::obj_offset_in_bytes(), monitor); - b(done); - - bind(no_recursive_unlock); + beq(CCR0, free_slot); // recursive unlock // } else if (Atomic::cmpxchg_ptr(displaced_header, obj->mark_addr(), monitor) == monitor) { // // We swapped the unlocked mark in displaced_header into the object's mark word. @@ -218,7 +221,7 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { // If we still have a lightweight lock, unlock the object and be done. // The object address from the monitor is in object. - ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); + if (!UseBiasedLocking) ld(object, BasicObjectLock::obj_offset_in_bytes(), monitor); addi(object_mark_addr, object, oopDesc::mark_offset_in_bytes()); // We have the displaced header in displaced_header. If the lock is still @@ -229,17 +232,11 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { /*current_value=*/current_header, /*compare_value=*/monitor, /*exchange_value=*/displaced_header, /*where=*/object_mark_addr, - MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, - MacroAssembler::cmpxchgx_hint_release_lock()); - bne(CCR0, slow_case); - - // Exchange worked, do monitor->set_obj(NULL). - li(R0, 0); - // Must realease earlier (see cmpxchgd above). - // release(); - std(R0, BasicObjectLock::obj_offset_in_bytes(), monitor); - b(done); - + MacroAssembler::MemBarRel, + MacroAssembler::cmpxchgx_hint_release_lock(), + noreg, + &slow_case); + b(free_slot); // } else { // // Slow path. @@ -249,9 +246,17 @@ void InterpreterMacroAssembler::unlock_object(Register monitor) { // we need to get into the slow case. bind(slow_case); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), - monitor, /*check_for_exceptions=*/false); + monitor, check_for_exceptions CC_INTERP_ONLY(&& false)); // } + Label done; + b(done); // Monitor register may be overwritten! Runtime has already freed the slot. + + // Exchange worked, do monitor->set_obj(NULL); + align(32, 12); + bind(free_slot); + li(R0, 0); + std(R0, BasicObjectLock::obj_offset_in_bytes(), monitor); bind(done); } } @@ -375,6 +380,7 @@ void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, TosSta call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit), /*check_exceptions=*/false); + align(32, 12); bind(jvmti_post_done); } } diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp index d4d3f165dbe..a189e30043c 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -37,6 +37,8 @@ class InterpreterMacroAssembler: public MacroAssembler { public: InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {} + void null_check_throw(Register a, int offset, Register temp_reg); + // Handy address generation macros #define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread #define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method @@ -51,15 +53,16 @@ class InterpreterMacroAssembler: public MacroAssembler { // Object locking void lock_object (Register lock_reg, Register obj_reg); - void unlock_object(Register lock_reg); + void unlock_object(Register lock_reg, bool check_for_exceptions = true); // Debugging void verify_oop(Register reg, TosState state = atos); // only if +VerifyOops && state == atos // support for jvmdi/jvmpi void notify_method_entry(); - void notify_method_exit(bool save_result, TosState state); + void notify_method_exit(bool is_native_method, TosState state); +#ifdef CC_INTERP // Convert the current TOP_IJAVA_FRAME into a PARENT_IJAVA_FRAME // (using parent_frame_resize) and push a new interpreter // TOP_IJAVA_FRAME (using frame_size). @@ -84,6 +87,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void pop_interpreter_state(bool prev_state_may_be_0); void restore_prev_state(); +#endif }; #endif // CPU_PPC_VM_INTERP_MASM_PPC_64_HPP diff --git a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp index 9e3d61a8367..3cc1b7f07e9 100644 --- a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp @@ -396,18 +396,14 @@ address AbstractInterpreterGenerator::generate_result_handler_for(BasicType type // Label done; - Label is_false; - address entry = __ pc(); switch (type) { case T_BOOLEAN: - __ cmpwi(CCR0, R3_RET, 0); - __ beq(CCR0, is_false); - __ li(R3_RET, 1); - __ b(done); - __ bind(is_false); - __ li(R3_RET, 0); + // convert !=0 to 1 + __ neg(R0, R3_RET); + __ orr(R0, R3_RET, R0); + __ srwi(R3_RET, R0, 31); break; case T_BYTE: // sign extend 8 bits @@ -478,7 +474,7 @@ address InterpreterGenerator::generate_abstract_entry(void) { // Push a new C frame and save LR. __ save_LR_CR(R0); - __ push_frame_abi112_nonvolatiles(0, R11_scratch1); + __ push_frame_abi112(0, R11_scratch1); // This is not a leaf but we have a JavaFrameAnchor now and we will // check (create) exceptions afterward so this is ok. @@ -491,8 +487,12 @@ address InterpreterGenerator::generate_abstract_entry(void) { // Reset JavaFrameAnchor from call_VM_leaf above. __ reset_last_Java_frame(); +#ifdef CC_INTERP // Return to frame manager, it will handle the pending exception. __ blr(); +#else + Unimplemented(); +#endif return entry; } @@ -503,16 +503,20 @@ address InterpreterGenerator::generate_accessor_entry(void) { if(!UseFastAccessorMethods && (!FLAG_IS_ERGO(UseFastAccessorMethods))) return NULL; - Label Ldone, Lslow_path; + Label Lslow_path, Lacquire; - const Register Rthis = R3_ARG1, + const Register + Rclass_or_obj = R3_ARG1, Rconst_method = R4_ARG2, Rcodes = Rconst_method, Rcpool_cache = R5_ARG3, Rscratch = R11_scratch1, Rjvmti_mode = Rscratch, Roffset = R12_scratch2, - Rflags = R6_ARG4; + Rflags = R6_ARG4, + Rbtable = R7_ARG5; + + static address branch_table[number_of_states]; address entry = __ pc(); @@ -521,13 +525,9 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Also check for JVMTI mode // Check for null obj, take slow path if so. -#ifdef CC_INTERP - __ ld(Rthis, Interpreter::stackElementSize, R17_tos); -#else - Unimplemented() -#endif + __ ld(Rclass_or_obj, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); __ lwz(Rjvmti_mode, thread_(interp_only_mode)); - __ cmpdi(CCR1, Rthis, 0); + __ cmpdi(CCR1, Rclass_or_obj, 0); __ cmpwi(CCR0, Rjvmti_mode, 0); __ crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); __ beq(CCR0, Lslow_path); // this==null or jvmti_mode!=0 @@ -560,58 +560,127 @@ address InterpreterGenerator::generate_accessor_entry(void) { __ ld(Rflags, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::flags_offset()), Rcpool_cache); __ ld(Roffset, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::f2_offset()), Rcpool_cache); - // Get field type. - // (Rflags>>ConstantPoolCacheEntry::tos_state_shift)&((1<print_cr("accessor_entry: branch_table[%d] = 0x%llx (opcode 0x%llx)", i, branch_table[i], *((unsigned int*)branch_table[i])); + } +#endif __ bind(Lslow_path); assert(Interpreter::entry_for_kind(Interpreter::zerolocals), "Normal entry must have been generated by now"); @@ -670,18 +739,14 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // continue and the thread will safepoint at the next bytecode dispatch. // If the receiver is null then it is OK to jump to the slow path. -#ifdef CC_INTERP - __ ld(R3_RET, Interpreter::stackElementSize, R17_tos); // get receiver -#else - Unimplemented(); -#endif + __ ld(R3_RET, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); // get receiver // Check if receiver == NULL and go the slow path. __ cmpdi(CCR0, R3_RET, 0); __ beq(CCR0, slow_path); // Load the value of the referent field. - __ load_heap_oop_not_null(R3_RET, referent_offset, R3_RET); + __ load_heap_oop(R3_RET, referent_offset, R3_RET); // Generate the G1 pre-barrier code to log the value of // the referent field in an SATB buffer. Note with diff --git a/hotspot/src/cpu/ppc/vm/jni_ppc.h b/hotspot/src/cpu/ppc/vm/jni_ppc.h index e10dfd0583c..da8cc361c14 100644 --- a/hotspot/src/cpu/ppc/vm/jni_ppc.h +++ b/hotspot/src/cpu/ppc/vm/jni_ppc.h @@ -40,8 +40,10 @@ #define JNIIMPORT #endif - #define JNICALL - typedef int jint; +#define JNICALL + +typedef int jint; + #if defined(_LP64) typedef long jlong; #else diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index f4b7c5e7652..80a53fc9afb 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -97,8 +97,10 @@ void MacroAssembler::store_sized_value(Register dst, RegisterOrConstant offs, Re } } -void MacroAssembler::align(int modulus) { - while (offset() % modulus != 0) nop(); +void MacroAssembler::align(int modulus, int max, int rem) { + int padding = (rem + modulus - (offset() % modulus)) % modulus; + if (padding > max) return; + for (int c = (padding >> 2); c > 0; --c) { nop(); } } // Issue instructions that calculate given TOC from global TOC. @@ -186,16 +188,25 @@ address MacroAssembler::get_address_of_calculate_address_from_global_toc_at(addr #ifdef _LP64 // Patch compressed oops or klass constants. +// Assembler sequence is +// 1) compressed oops: +// lis rx = const.hi +// ori rx = rx | const.lo +// 2) compressed klass: +// lis rx = const.hi +// clrldi rx = rx & 0xFFFFffff // clearMS32b, optional +// ori rx = rx | const.lo +// Clrldi will be passed by. int MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop data) { assert(UseCompressedOops, "Should only patch compressed oops"); const address inst2_addr = a; const int inst2 = *(int *)inst2_addr; - // The relocation points to the second instruction, the addi, - // and the addi reads and writes the same register dst. - const int dst = inv_rt_field(inst2); - assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + // The relocation points to the second instruction, the ori, + // and the ori reads and writes the same register dst. + const int dst = inv_rta_field(inst2); + assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be addi reading and writing dst"); // Now, find the preceding addis which writes to dst. int inst1 = 0; address inst1_addr = inst2_addr - BytesPerInstWord; @@ -210,8 +221,9 @@ int MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop dat int xc = (data >> 16) & 0xffff; int xd = (data >> 0) & 0xffff; - set_imm((int *)inst1_addr,((short)(xc + ((xd & 0x8000) != 0 ? 1 : 0)))); // see enc_load_con_narrow1/2 + set_imm((int *)inst1_addr, (short)(xc)); // see enc_load_con_narrow_hi/_lo set_imm((int *)inst2_addr, (short)(xd)); + return (int)((intptr_t)inst2_addr - (intptr_t)inst1_addr); } @@ -222,10 +234,10 @@ narrowOop MacroAssembler::get_narrow_oop(address a, address bound) { const address inst2_addr = a; const int inst2 = *(int *)inst2_addr; - // The relocation points to the second instruction, the addi, - // and the addi reads and writes the same register dst. - const int dst = inv_rt_field(inst2); - assert(is_addi(inst2) && inv_ra_field(inst2) == dst, "must be addi reading and writing dst"); + // The relocation points to the second instruction, the ori, + // and the ori reads and writes the same register dst. + const int dst = inv_rta_field(inst2); + assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be addi reading and writing dst"); // Now, find the preceding lis which writes to dst. int inst1 = 0; address inst1_addr = inst2_addr - BytesPerInstWord; @@ -238,8 +250,9 @@ narrowOop MacroAssembler::get_narrow_oop(address a, address bound) { } assert(inst1_found, "inst is not lis"); - uint xl = ((unsigned int) (get_imm(inst2_addr,0) & 0xffff)); - uint xh = (((((xl & 0x8000) != 0 ? -1 : 0) + get_imm(inst1_addr,0)) & 0xffff) << 16); + uint xl = ((unsigned int) (get_imm(inst2_addr, 0) & 0xffff)); + uint xh = (((get_imm(inst1_addr, 0)) & 0xffff) << 16); + return (int) (xl | xh); } #endif // _LP64 @@ -252,13 +265,10 @@ void MacroAssembler::load_const_from_method_toc(Register dst, AddressLiteral& a, // FIXME: We should insert relocation information for oops at the constant // pool entries instead of inserting it at the loads; patching of a constant // pool entry should be less expensive. - Unimplemented(); - if (false) { - address oop_address = address_constant((address)a.value(), RelocationHolder::none); - // Relocate at the pc of the load. - relocate(a.rspec()); - toc_offset = (int)(oop_address - code()->consts()->start()); - } + address oop_address = address_constant((address)a.value(), RelocationHolder::none); + // Relocate at the pc of the load. + relocate(a.rspec()); + toc_offset = (int)(oop_address - code()->consts()->start()); ld_largeoffset_unchecked(dst, toc_offset, toc, true); } @@ -532,7 +542,7 @@ void MacroAssembler::set_dest_of_bc_far_at(address instruction_addr, address des masm.b(dest); } } - ICache::invalidate_range(instruction_addr, code_size); + ICache::ppc64_flush_icache_bytes(instruction_addr, code_size); } // Emit a NOT mt-safe patchable 64 bit absolute call/jump. @@ -673,7 +683,7 @@ void MacroAssembler::set_dest_of_bxx64_patchable_at(address instruction_addr, ad CodeBuffer buf(instruction_addr, code_size); MacroAssembler masm(&buf); masm.bxx64_patchable(dest, relocInfo::none, link); - ICache::invalidate_range(instruction_addr, code_size); + ICache::ppc64_flush_icache_bytes(instruction_addr, code_size); } // Get dest address of a bxx64_patchable instruction. @@ -964,6 +974,14 @@ address MacroAssembler::call_c(Register fd) { /*load env=*/true); } +address MacroAssembler::call_c_and_return_to_caller(Register fd) { + return branch_to(fd, /*and_link=*/false, + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/true); +} + address MacroAssembler::call_c(const FunctionDescriptor* fd, relocInfo::relocType rt) { if (rt != relocInfo::none) { // this call needs to be relocatable @@ -2315,7 +2333,7 @@ void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Ja if (last_Java_pc != noreg) std(last_Java_pc, in_bytes(JavaThread::last_Java_pc_offset()), R16_thread); - // set last_Java_sp last + // Set last_Java_sp last. std(last_Java_sp, in_bytes(JavaThread::last_Java_sp_offset()), R16_thread); } @@ -2454,6 +2472,57 @@ void MacroAssembler::reinit_heapbase(Register d, Register tmp) { } } +// Clear Array +// Kills both input registers. tmp == R0 is allowed. +void MacroAssembler::clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp) { + // Procedure for large arrays (uses data cache block zero instruction). + Label startloop, fast, fastloop, small_rest, restloop, done; + const int cl_size = VM_Version::get_cache_line_size(), + cl_dwords = cl_size>>3, + cl_dw_addr_bits = exact_log2(cl_dwords), + dcbz_min = 1; // Min count of dcbz executions, needs to be >0. + +//2: + cmpdi(CCR1, cnt_dwords, ((dcbz_min+1)<=dcbz_min lines included). + blt(CCR1, small_rest); // Too small. + rldicl_(tmp, base_ptr, 64-3, 64-cl_dw_addr_bits); // Extract dword offset within first cache line. + beq(CCR0, fast); // Already 128byte aligned. + + subfic(tmp, tmp, cl_dwords); + mtctr(tmp); // Set ctr to hit 128byte boundary (00). + andi(cnt_dwords, cnt_dwords, cl_dwords-1); // Rest in dwords. + mtctr(tmp); // Load counter. +//16: + bind(fastloop); + dcbz(base_ptr); // Clear 128byte aligned block. + addi(base_ptr, base_ptr, cl_size); + bdnz(fastloop); + if (InsertEndGroupPPC64) { endgroup(); } else { nop(); } +//20: + bind(small_rest); + cmpdi(CCR0, cnt_dwords, 0); // size 0? + beq(CCR0, done); // rest == 0 + li(tmp, 0); + mtctr(cnt_dwords); // Load counter. +//24: + bind(restloop); // Clear rest. + std(tmp, 0, base_ptr); // Clear 8byte aligned block. + addi(base_ptr, base_ptr, 8); + bdnz(restloop); +//27: + bind(done); +} + /////////////////////////////////////////// String intrinsics //////////////////////////////////////////// // Search for a single jchar in an jchar[]. @@ -2926,12 +2995,11 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) { if (!VerifyOops) { return; } - // will be preserved. + // Will be preserved. Register tmp = R11; assert(oop != tmp, "precondition"); unsigned int nbytes_save = 10*8; // 10 volatile gprs - address/* FunctionDescriptor** */fd = - StubRoutines::verify_oop_subroutine_entry_address(); + address/* FunctionDescriptor** */fd = StubRoutines::verify_oop_subroutine_entry_address(); // save tmp mr(R0, tmp); // kill tmp diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp index 7d0a94312d3..e3ba572c67f 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -58,9 +58,24 @@ class MacroAssembler: public Assembler { // Move register if destination register and target register are different inline void mr_if_needed(Register rd, Register rs); + inline void fmr_if_needed(FloatRegister rd, FloatRegister rs); + // This is dedicated for emitting scheduled mach nodes. For better + // readability of the ad file I put it here. + // Endgroups are not needed if + // - the scheduler is off + // - the scheduler found that there is a natural group end, in that + // case it reduced the size of the instruction used in the test + // yielding 'needed'. + inline void endgroup_if_needed(bool needed); + + // Memory barriers. + inline void membar(int bits); + inline void release(); + inline void acquire(); + inline void fence(); // nop padding - void align(int modulus); + void align(int modulus, int max = 252, int rem = 0); // // Constants, loading constants, TOC support @@ -295,6 +310,8 @@ class MacroAssembler: public Assembler { // Call a C function via a function descriptor and use full C // calling conventions. Updates and returns _last_calls_return_pc. address call_c(Register function_descriptor); + // For tail calls: only branch, don't link, so callee returns to caller of this function. + address call_c_and_return_to_caller(Register function_descriptor); address call_c(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt); address call_c_using_toc(const FunctionDescriptor* function_descriptor, relocInfo::relocType rt, Register toc); @@ -320,7 +337,7 @@ class MacroAssembler: public Assembler { // the entry point address entry_point, // flag which indicates if exception should be checked - bool check_exception=true + bool check_exception = true ); // Support for VM calls. This is the base routine called by the @@ -530,9 +547,7 @@ class MacroAssembler: public Assembler { inline void null_check_throw(Register a, int offset, Register temp_reg, address exception_entry); // Check accessed object for null. Use SIGTRAP-based null checks on AIX. - inline void ld_with_trap_null_check(Register d, int si16, Register s1); - // Variant for heap OOPs including decompression of compressed OOPs. - inline void load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant offs, Register s1); + inline void load_with_trap_null_check(Register d, int si16, Register s1); // Load heap oop and decompress. Loaded oop may not be null. inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg); @@ -584,6 +599,8 @@ class MacroAssembler: public Assembler { is_trap_range_check_g(x) || is_trap_range_check_ge(x); } + void clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp = R0); + // Needle of length 1. void string_indexof_1(Register result, Register haystack, Register haycnt, Register needle, jchar needleChar, @@ -630,7 +647,7 @@ class MacroAssembler: public Assembler { // TODO: verify method and klass metadata (compare against vptr?) void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} - void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} + void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line) {} #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp index 529f82468ef..93f31a70f5e 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp @@ -58,8 +58,25 @@ inline void MacroAssembler::round_to(Register r, int modulus) { // Move register if destination register and target register are different. inline void MacroAssembler::mr_if_needed(Register rd, Register rs) { - if(rs !=rd) mr(rd, rs); + if (rs != rd) mr(rd, rs); } +inline void MacroAssembler::fmr_if_needed(FloatRegister rd, FloatRegister rs) { + if (rs != rd) fmr(rd, rs); +} +inline void MacroAssembler::endgroup_if_needed(bool needed) { + if (needed) { + endgroup(); + } +} + +inline void MacroAssembler::membar(int bits) { + // TODO: use elemental_membar(bits) for Power 8 and disable optimization of acquire-release + // (Matcher::post_membar_release where we use PPC64_ONLY(xop == Op_MemBarRelease ||)) + if (bits & StoreLoad) sync(); else lwsync(); +} +inline void MacroAssembler::release() { membar(LoadStore | StoreStore); } +inline void MacroAssembler::acquire() { membar(LoadLoad | LoadStore); } +inline void MacroAssembler::fence() { membar(LoadLoad | LoadStore | StoreLoad | StoreStore); } // Address of the global TOC. inline address MacroAssembler::global_toc() { @@ -117,13 +134,12 @@ inline bool MacroAssembler::is_calculate_address_from_global_toc_at(address a, a inline bool MacroAssembler::is_set_narrow_oop(address a, address bound) { const address inst2_addr = a; const int inst2 = *(int *)a; + // The relocation points to the second instruction, the ori. + if (!is_ori(inst2)) return false; - // The relocation points to the second instruction, the addi. - if (!is_addi(inst2)) return false; - - // The addi reads and writes the same register dst. - const int dst = inv_rt_field(inst2); - if (inv_ra_field(inst2) != dst) return false; + // The ori reads and writes the same register dst. + const int dst = inv_rta_field(inst2); + if (inv_rs_field(inst2) != dst) return false; // Now, find the preceding addis which writes to dst. int inst1 = 0; @@ -266,9 +282,10 @@ inline void MacroAssembler::trap_ic_miss_check(Register a, Register b) { // Do an explicit null check if access to a+offset will not raise a SIGSEGV. // Either issue a trap instruction that raises SIGTRAP, or do a compare that // branches to exception_entry. -// No support for compressed oops (base page of heap). Does not distinguish +// No support for compressed oops (base page of heap). Does not distinguish // loads and stores. -inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, address exception_entry) { +inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, + address exception_entry) { if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { assert(UseSIGTRAP, "sanity"); @@ -285,7 +302,7 @@ inline void MacroAssembler::null_check_throw(Register a, int offset, Register te } } -inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Register s1) { +inline void MacroAssembler::load_with_trap_null_check(Register d, int si16, Register s1) { if (!os::zero_page_read_protected()) { if (TrapBasedNullChecks) { trap_null_check(s1); @@ -294,17 +311,6 @@ inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Regist ld(d, si16, s1); } -// Attention: No null check for loaded uncompressed OOP. Can be used for loading klass field. -inline void MacroAssembler::load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant si16, - Register s1) { - if ( !os::zero_page_read_protected()) { - if (TrapBasedNullChecks) { - trap_null_check(s1); - } - } - load_heap_oop_not_null(d, si16, s1); -} - inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) { if (UseCompressedOops) { lwz(d, offs, s1); diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp index f145e8c6d7d..6709c8ce680 100644 --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -31,12 +31,16 @@ #define __ _masm-> +#ifdef CC_INTERP +#define EXCEPTION_ENTRY StubRoutines::throw_NullPointerException_at_call_entry() +#else +#define EXCEPTION_ENTRY Interpreter::throw_NullPointerException_entry() +#endif + #ifdef PRODUCT #define BLOCK_COMMENT(str) // nothing -#define STOP(error) stop(error) #else #define BLOCK_COMMENT(str) __ block_comment(str) -#define STOP(error) block_comment(error); __ stop(error) #endif #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") @@ -167,7 +171,7 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), ""); Label L; - __ ld(temp2, __ argument_offset(temp2, temp2, 0), R17_tos); + __ ld(temp2, __ argument_offset(temp2, temp2, 0), CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); __ cmpd(CCR1, temp2, recv); __ beq(CCR1, L); __ stop("receiver not on stack"); @@ -194,7 +198,7 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* return NULL; } - Register argbase = R17_tos; // parameter (preserved) + Register argbase = CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp); // parameter (preserved) Register argslot = R3; Register temp1 = R6; Register param_size = R7; @@ -271,7 +275,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Register member_reg, bool for_compiler_entry) { assert(is_signature_polymorphic(iid), "expected invoke iid"); - Register temp1 = (for_compiler_entry ? R21_tmp1 : R7); + Register temp1 = (for_compiler_entry ? R25_tmp5 : R7); Register temp2 = (for_compiler_entry ? R22_tmp2 : R8); Register temp3 = (for_compiler_entry ? R23_tmp3 : R9); Register temp4 = (for_compiler_entry ? R24_tmp4 : R10); @@ -295,11 +299,10 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, __ verify_oop(receiver_reg); if (iid == vmIntrinsics::_linkToSpecial) { // Don't actually load the klass; just null-check the receiver. - __ null_check_throw(receiver_reg, 0, temp1, StubRoutines::throw_NullPointerException_at_call_entry()); + __ null_check_throw(receiver_reg, -1, temp1, EXCEPTION_ENTRY); } else { // load receiver klass itself - __ null_check_throw(receiver_reg, oopDesc::klass_offset_in_bytes(), - temp1, StubRoutines::throw_NullPointerException_at_call_entry()); + __ null_check_throw(receiver_reg, oopDesc::klass_offset_in_bytes(), temp1, EXCEPTION_ENTRY); __ load_klass(temp1_recv_klass, receiver_reg); __ verify_klass_ptr(temp1_recv_klass); } @@ -451,7 +454,7 @@ void trace_method_handle_stub(const char* adaptername, if (Verbose) { tty->print_cr("Registers:"); const int abi_offset = frame::abi_112_size / 8; - for (int i = R3->encoding(); i <= R13->encoding(); i++) { + for (int i = R3->encoding(); i <= R12->encoding(); i++) { Register r = as_Register(i); int count = i - R3->encoding(); // The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_112_size)). @@ -490,7 +493,7 @@ void trace_method_handle_stub(const char* adaptername, trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); } - // safely create a frame and call frame::describe + // Safely create a frame and call frame::describe. intptr_t *dump_sp = trace_calling_frame.sender_sp(); frame dump_frame = frame(dump_sp); @@ -531,7 +534,7 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt __ mr(R6_ARG4, R1_SP); __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub)); - __ restore_volatile_gprs(R1_SP, 112); // except R0 + __ restore_volatile_gprs(R1_SP, 112); // Except R0. __ pop_frame(); __ restore_LR_CR(R0); diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp index fecb5813384..434ec7c3893 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp @@ -118,7 +118,7 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { a->bl(trampoline_stub_addr); } - ICache::invalidate_range(addr_call, code_size); + ICache::ppc64_flush_icache_bytes(addr_call, code_size); } address NativeCall::get_trampoline() { @@ -182,11 +182,13 @@ address NativeMovConstReg::next_instruction_address() const { intptr_t NativeMovConstReg::data() const { address addr = addr_at(0); - CodeBlob* cb = CodeCache::find_blob_unsafe(addr); if (MacroAssembler::is_load_const_at(addr)) { return MacroAssembler::get_const(addr); - } else if (MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) { + } + + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); + if (MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) { narrowOop no = (narrowOop)MacroAssembler::get_narrow_oop(addr, cb->content_begin()); return cast_from_oop(oopDesc::decode_heap_oop(no)); } else { @@ -213,19 +215,24 @@ address NativeMovConstReg::set_data_plain(intptr_t data, CodeBlob *cb) { } else if (cb != NULL && MacroAssembler::is_calculate_address_from_global_toc_at(addr, cb->content_begin())) { // A calculation relative to the global TOC. - const int invalidated_range = - MacroAssembler::patch_calculate_address_from_global_toc_at(addr, cb->content_begin(), - (address)data); - const address start = invalidated_range < 0 ? addr + invalidated_range : addr; - // FIXME: - const int range = invalidated_range < 0 ? 4 - invalidated_range : 8; - ICache::invalidate_range(start, range); + if (MacroAssembler::get_address_of_calculate_address_from_global_toc_at(addr, cb->content_begin()) != + (address)data) { + const int invalidated_range = + MacroAssembler::patch_calculate_address_from_global_toc_at(addr, cb->content_begin(), + (address)data); + const address start = invalidated_range < 0 ? addr + invalidated_range : addr; + // FIXME: + const int range = invalidated_range < 0 ? 4 - invalidated_range : 8; + ICache::ppc64_flush_icache_bytes(start, range); + } next_address = addr + 1 * BytesPerInstWord; } else if (MacroAssembler::is_load_const_at(addr)) { // A normal 5 instruction load_const code sequence. - // This is not mt safe, ok in methods like CodeBuffer::copy_code(). - MacroAssembler::patch_const(addr, (long)data); - ICache::invalidate_range(addr, load_const_instruction_size); + if (MacroAssembler::get_const(addr) != (long)data) { + // This is not mt safe, ok in methods like CodeBuffer::copy_code(). + MacroAssembler::patch_const(addr, (long)data); + ICache::ppc64_flush_icache_bytes(addr, load_const_instruction_size); + } next_address = addr + 5 * BytesPerInstWord; } else if (MacroAssembler::is_bl(* (int*) addr)) { // A single branch-and-link instruction. @@ -234,7 +241,7 @@ address NativeMovConstReg::set_data_plain(intptr_t data, CodeBlob *cb) { CodeBuffer cb(addr, code_size + 1); MacroAssembler* a = new MacroAssembler(&cb); a->bl((address) data); - ICache::invalidate_range(addr, code_size); + ICache::ppc64_flush_icache_bytes(addr, code_size); next_address = addr + code_size; } else { ShouldNotReachHere(); @@ -279,12 +286,13 @@ void NativeMovConstReg::set_data(intptr_t data) { void NativeMovConstReg::set_narrow_oop(narrowOop data, CodeBlob *code /* = NULL */) { address addr = addr_at(0); CodeBlob* cb = (code) ? code : CodeCache::find_blob(instruction_address()); + if (MacroAssembler::get_narrow_oop(addr, cb->content_begin()) == (long)data) return; const int invalidated_range = MacroAssembler::patch_set_narrow_oop(addr, cb->content_begin(), (long)data); const address start = invalidated_range < 0 ? addr + invalidated_range : addr; // FIXME: const int range = invalidated_range < 0 ? 4 - invalidated_range : 8; - ICache::invalidate_range(start, range); + ICache::ppc64_flush_icache_bytes(start, range); } // Do not use an assertion here. Let clients decide whether they only @@ -292,15 +300,16 @@ void NativeMovConstReg::set_narrow_oop(narrowOop data, CodeBlob *code /* = NULL #ifdef ASSERT void NativeMovConstReg::verify() { address addr = addr_at(0); - CodeBlob* cb = CodeCache::find_blob_unsafe(addr); // find_nmethod() asserts if nmethod is zombie. if (! MacroAssembler::is_load_const_at(addr) && - ! MacroAssembler::is_load_const_from_method_toc_at(addr) && - ! (cb != NULL && MacroAssembler::is_calculate_address_from_global_toc_at(addr, cb->content_begin())) && - ! (cb != NULL && MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) && - ! MacroAssembler::is_bl(*((int*) addr))) { - tty->print_cr("not a NativeMovConstReg at " PTR_FORMAT, addr); - // TODO: PPC port Disassembler::decode(addr, 20, 20, tty); - fatal(err_msg("not a NativeMovConstReg at " PTR_FORMAT, addr)); + ! MacroAssembler::is_load_const_from_method_toc_at(addr)) { + CodeBlob* cb = CodeCache::find_blob_unsafe(addr); // find_nmethod() asserts if nmethod is zombie. + if (! (cb != NULL && MacroAssembler::is_calculate_address_from_global_toc_at(addr, cb->content_begin())) && + ! (cb != NULL && MacroAssembler::is_set_narrow_oop(addr, cb->content_begin())) && + ! MacroAssembler::is_bl(*((int*) addr))) { + tty->print_cr("not a NativeMovConstReg at " PTR_FORMAT, addr); + // TODO: PPC port: Disassembler::decode(addr, 20, 20, tty); + fatal(err_msg("not a NativeMovConstReg at " PTR_FORMAT, addr)); + } } } #endif // ASSERT @@ -326,7 +335,7 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add a->illtrap(); } } - ICache::invalidate_range(verified_entry, code_size); + ICache::ppc64_flush_icache_bytes(verified_entry, code_size); } #ifdef ASSERT diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index c2ff51183c1..6c7db6d25b2 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -132,7 +132,7 @@ inline NativeInstruction* nativeInstruction_at(address address) { class NativeCall: public NativeInstruction { public: - enum specific_constants { + enum ppc_specific_constants { load_const_instruction_size = 28, load_const_from_method_toc_instruction_size = 16, instruction_size = 16 // Used in shared code for calls with reloc_info. @@ -240,7 +240,7 @@ inline NativeFarCall* nativeFarCall_at(address instr) { class NativeMovConstReg: public NativeInstruction { public: - enum specific_constants { + enum ppc_specific_constants { load_const_instruction_size = 20, load_const_from_method_toc_instruction_size = 8, instruction_size = 8 // Used in shared code for calls with reloc_info. @@ -279,7 +279,7 @@ class NativeJump: public NativeInstruction { // We use MacroAssembler::b64_patchable() for implementing a // jump-anywhere instruction. - enum specific_constants { + enum ppc_specific_constants { instruction_size = MacroAssembler::b64_patchable_size }; @@ -384,7 +384,6 @@ class NativeCallTrampolineStub : public NativeInstruction { void set_destination(address new_destination); }; - inline bool is_NativeCallTrampolineStub_at(address address) { int first_instr = *(int*)address; return Assembler::is_addis(first_instr) && diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad new file mode 100644 index 00000000000..cae2015bbab --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -0,0 +1,12059 @@ +// +// Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright 2012, 2013 SAP AG. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +// +// PPC64 Architecture Description File +// + +//----------REGISTER DEFINITION BLOCK------------------------------------------ +// This information is used by the matcher and the register allocator to +// describe individual registers and classes of registers within the target +// architecture. +register %{ +//----------Architecture Description Register Definitions---------------------- +// General Registers +// "reg_def" name (register save type, C convention save type, +// ideal register type, encoding); +// +// Register Save Types: +// +// NS = No-Save: The register allocator assumes that these registers +// can be used without saving upon entry to the method, & +// that they do not need to be saved at call sites. +// +// SOC = Save-On-Call: The register allocator assumes that these registers +// can be used without saving upon entry to the method, +// but that they must be saved at call sites. +// These are called "volatiles" on ppc. +// +// SOE = Save-On-Entry: The register allocator assumes that these registers +// must be saved before using them upon entry to the +// method, but they do not need to be saved at call +// sites. +// These are called "nonvolatiles" on ppc. +// +// AS = Always-Save: The register allocator assumes that these registers +// must be saved before using them upon entry to the +// method, & that they must be saved at call sites. +// +// Ideal Register Type is used to determine how to save & restore a +// register. Op_RegI will get spilled with LoadI/StoreI, Op_RegP will get +// spilled with LoadP/StoreP. If the register supports both, use Op_RegI. +// +// The encoding number is the actual bit-pattern placed into the opcodes. +// +// PPC64 register definitions, based on the 64-bit PowerPC ELF ABI +// Supplement Version 1.7 as of 2003-10-29. +// +// For each 64-bit register we must define two registers: the register +// itself, e.g. R3, and a corresponding virtual other (32-bit-)'half', +// e.g. R3_H, which is needed by the allocator, but is not used +// for stores, loads, etc. + +// ---------------------------- +// Integer/Long Registers +// ---------------------------- + + // PPC64 has 32 64-bit integer registers. + + // types: v = volatile, nv = non-volatile, s = system + reg_def R0 ( SOC, SOC, Op_RegI, 0, R0->as_VMReg() ); // v used in prologs + reg_def R0_H ( SOC, SOC, Op_RegI, 99, R0->as_VMReg()->next() ); + reg_def R1 ( NS, NS, Op_RegI, 1, R1->as_VMReg() ); // s SP + reg_def R1_H ( NS, NS, Op_RegI, 99, R1->as_VMReg()->next() ); + reg_def R2 ( SOC, SOC, Op_RegI, 2, R2->as_VMReg() ); // v TOC + reg_def R2_H ( SOC, SOC, Op_RegI, 99, R2->as_VMReg()->next() ); + reg_def R3 ( SOC, SOC, Op_RegI, 3, R3->as_VMReg() ); // v iarg1 & iret + reg_def R3_H ( SOC, SOC, Op_RegI, 99, R3->as_VMReg()->next() ); + reg_def R4 ( SOC, SOC, Op_RegI, 4, R4->as_VMReg() ); // iarg2 + reg_def R4_H ( SOC, SOC, Op_RegI, 99, R4->as_VMReg()->next() ); + reg_def R5 ( SOC, SOC, Op_RegI, 5, R5->as_VMReg() ); // v iarg3 + reg_def R5_H ( SOC, SOC, Op_RegI, 99, R5->as_VMReg()->next() ); + reg_def R6 ( SOC, SOC, Op_RegI, 6, R6->as_VMReg() ); // v iarg4 + reg_def R6_H ( SOC, SOC, Op_RegI, 99, R6->as_VMReg()->next() ); + reg_def R7 ( SOC, SOC, Op_RegI, 7, R7->as_VMReg() ); // v iarg5 + reg_def R7_H ( SOC, SOC, Op_RegI, 99, R7->as_VMReg()->next() ); + reg_def R8 ( SOC, SOC, Op_RegI, 8, R8->as_VMReg() ); // v iarg6 + reg_def R8_H ( SOC, SOC, Op_RegI, 99, R8->as_VMReg()->next() ); + reg_def R9 ( SOC, SOC, Op_RegI, 9, R9->as_VMReg() ); // v iarg7 + reg_def R9_H ( SOC, SOC, Op_RegI, 99, R9->as_VMReg()->next() ); + reg_def R10 ( SOC, SOC, Op_RegI, 10, R10->as_VMReg() ); // v iarg8 + reg_def R10_H( SOC, SOC, Op_RegI, 99, R10->as_VMReg()->next()); + reg_def R11 ( SOC, SOC, Op_RegI, 11, R11->as_VMReg() ); // v ENV / scratch + reg_def R11_H( SOC, SOC, Op_RegI, 99, R11->as_VMReg()->next()); + reg_def R12 ( SOC, SOC, Op_RegI, 12, R12->as_VMReg() ); // v scratch + reg_def R12_H( SOC, SOC, Op_RegI, 99, R12->as_VMReg()->next()); + reg_def R13 ( NS, NS, Op_RegI, 13, R13->as_VMReg() ); // s system thread id + reg_def R13_H( NS, NS, Op_RegI, 99, R13->as_VMReg()->next()); + reg_def R14 ( SOC, SOE, Op_RegI, 14, R14->as_VMReg() ); // nv + reg_def R14_H( SOC, SOE, Op_RegI, 99, R14->as_VMReg()->next()); + reg_def R15 ( SOC, SOE, Op_RegI, 15, R15->as_VMReg() ); // nv + reg_def R15_H( SOC, SOE, Op_RegI, 99, R15->as_VMReg()->next()); + reg_def R16 ( SOC, SOE, Op_RegI, 16, R16->as_VMReg() ); // nv + reg_def R16_H( SOC, SOE, Op_RegI, 99, R16->as_VMReg()->next()); + reg_def R17 ( SOC, SOE, Op_RegI, 17, R17->as_VMReg() ); // nv + reg_def R17_H( SOC, SOE, Op_RegI, 99, R17->as_VMReg()->next()); + reg_def R18 ( SOC, SOE, Op_RegI, 18, R18->as_VMReg() ); // nv + reg_def R18_H( SOC, SOE, Op_RegI, 99, R18->as_VMReg()->next()); + reg_def R19 ( SOC, SOE, Op_RegI, 19, R19->as_VMReg() ); // nv + reg_def R19_H( SOC, SOE, Op_RegI, 99, R19->as_VMReg()->next()); + reg_def R20 ( SOC, SOE, Op_RegI, 20, R20->as_VMReg() ); // nv + reg_def R20_H( SOC, SOE, Op_RegI, 99, R20->as_VMReg()->next()); + reg_def R21 ( SOC, SOE, Op_RegI, 21, R21->as_VMReg() ); // nv + reg_def R21_H( SOC, SOE, Op_RegI, 99, R21->as_VMReg()->next()); + reg_def R22 ( SOC, SOE, Op_RegI, 22, R22->as_VMReg() ); // nv + reg_def R22_H( SOC, SOE, Op_RegI, 99, R22->as_VMReg()->next()); + reg_def R23 ( SOC, SOE, Op_RegI, 23, R23->as_VMReg() ); // nv + reg_def R23_H( SOC, SOE, Op_RegI, 99, R23->as_VMReg()->next()); + reg_def R24 ( SOC, SOE, Op_RegI, 24, R24->as_VMReg() ); // nv + reg_def R24_H( SOC, SOE, Op_RegI, 99, R24->as_VMReg()->next()); + reg_def R25 ( SOC, SOE, Op_RegI, 25, R25->as_VMReg() ); // nv + reg_def R25_H( SOC, SOE, Op_RegI, 99, R25->as_VMReg()->next()); + reg_def R26 ( SOC, SOE, Op_RegI, 26, R26->as_VMReg() ); // nv + reg_def R26_H( SOC, SOE, Op_RegI, 99, R26->as_VMReg()->next()); + reg_def R27 ( SOC, SOE, Op_RegI, 27, R27->as_VMReg() ); // nv + reg_def R27_H( SOC, SOE, Op_RegI, 99, R27->as_VMReg()->next()); + reg_def R28 ( SOC, SOE, Op_RegI, 28, R28->as_VMReg() ); // nv + reg_def R28_H( SOC, SOE, Op_RegI, 99, R28->as_VMReg()->next()); + reg_def R29 ( SOC, SOE, Op_RegI, 29, R29->as_VMReg() ); // nv + reg_def R29_H( SOC, SOE, Op_RegI, 99, R29->as_VMReg()->next()); + reg_def R30 ( SOC, SOE, Op_RegI, 30, R30->as_VMReg() ); // nv + reg_def R30_H( SOC, SOE, Op_RegI, 99, R30->as_VMReg()->next()); + reg_def R31 ( SOC, SOE, Op_RegI, 31, R31->as_VMReg() ); // nv + reg_def R31_H( SOC, SOE, Op_RegI, 99, R31->as_VMReg()->next()); + + +// ---------------------------- +// Float/Double Registers +// ---------------------------- + + // Double Registers + // The rules of ADL require that double registers be defined in pairs. + // Each pair must be two 32-bit values, but not necessarily a pair of + // single float registers. In each pair, ADLC-assigned register numbers + // must be adjacent, with the lower number even. Finally, when the + // CPU stores such a register pair to memory, the word associated with + // the lower ADLC-assigned number must be stored to the lower address. + + // PPC64 has 32 64-bit floating-point registers. Each can store a single + // or double precision floating-point value. + + // types: v = volatile, nv = non-volatile, s = system + reg_def F0 ( SOC, SOC, Op_RegF, 0, F0->as_VMReg() ); // v scratch + reg_def F0_H ( SOC, SOC, Op_RegF, 99, F0->as_VMReg()->next() ); + reg_def F1 ( SOC, SOC, Op_RegF, 1, F1->as_VMReg() ); // v farg1 & fret + reg_def F1_H ( SOC, SOC, Op_RegF, 99, F1->as_VMReg()->next() ); + reg_def F2 ( SOC, SOC, Op_RegF, 2, F2->as_VMReg() ); // v farg2 + reg_def F2_H ( SOC, SOC, Op_RegF, 99, F2->as_VMReg()->next() ); + reg_def F3 ( SOC, SOC, Op_RegF, 3, F3->as_VMReg() ); // v farg3 + reg_def F3_H ( SOC, SOC, Op_RegF, 99, F3->as_VMReg()->next() ); + reg_def F4 ( SOC, SOC, Op_RegF, 4, F4->as_VMReg() ); // v farg4 + reg_def F4_H ( SOC, SOC, Op_RegF, 99, F4->as_VMReg()->next() ); + reg_def F5 ( SOC, SOC, Op_RegF, 5, F5->as_VMReg() ); // v farg5 + reg_def F5_H ( SOC, SOC, Op_RegF, 99, F5->as_VMReg()->next() ); + reg_def F6 ( SOC, SOC, Op_RegF, 6, F6->as_VMReg() ); // v farg6 + reg_def F6_H ( SOC, SOC, Op_RegF, 99, F6->as_VMReg()->next() ); + reg_def F7 ( SOC, SOC, Op_RegF, 7, F7->as_VMReg() ); // v farg7 + reg_def F7_H ( SOC, SOC, Op_RegF, 99, F7->as_VMReg()->next() ); + reg_def F8 ( SOC, SOC, Op_RegF, 8, F8->as_VMReg() ); // v farg8 + reg_def F8_H ( SOC, SOC, Op_RegF, 99, F8->as_VMReg()->next() ); + reg_def F9 ( SOC, SOC, Op_RegF, 9, F9->as_VMReg() ); // v farg9 + reg_def F9_H ( SOC, SOC, Op_RegF, 99, F9->as_VMReg()->next() ); + reg_def F10 ( SOC, SOC, Op_RegF, 10, F10->as_VMReg() ); // v farg10 + reg_def F10_H( SOC, SOC, Op_RegF, 99, F10->as_VMReg()->next()); + reg_def F11 ( SOC, SOC, Op_RegF, 11, F11->as_VMReg() ); // v farg11 + reg_def F11_H( SOC, SOC, Op_RegF, 99, F11->as_VMReg()->next()); + reg_def F12 ( SOC, SOC, Op_RegF, 12, F12->as_VMReg() ); // v farg12 + reg_def F12_H( SOC, SOC, Op_RegF, 99, F12->as_VMReg()->next()); + reg_def F13 ( SOC, SOC, Op_RegF, 13, F13->as_VMReg() ); // v farg13 + reg_def F13_H( SOC, SOC, Op_RegF, 99, F13->as_VMReg()->next()); + reg_def F14 ( SOC, SOE, Op_RegF, 14, F14->as_VMReg() ); // nv + reg_def F14_H( SOC, SOE, Op_RegF, 99, F14->as_VMReg()->next()); + reg_def F15 ( SOC, SOE, Op_RegF, 15, F15->as_VMReg() ); // nv + reg_def F15_H( SOC, SOE, Op_RegF, 99, F15->as_VMReg()->next()); + reg_def F16 ( SOC, SOE, Op_RegF, 16, F16->as_VMReg() ); // nv + reg_def F16_H( SOC, SOE, Op_RegF, 99, F16->as_VMReg()->next()); + reg_def F17 ( SOC, SOE, Op_RegF, 17, F17->as_VMReg() ); // nv + reg_def F17_H( SOC, SOE, Op_RegF, 99, F17->as_VMReg()->next()); + reg_def F18 ( SOC, SOE, Op_RegF, 18, F18->as_VMReg() ); // nv + reg_def F18_H( SOC, SOE, Op_RegF, 99, F18->as_VMReg()->next()); + reg_def F19 ( SOC, SOE, Op_RegF, 19, F19->as_VMReg() ); // nv + reg_def F19_H( SOC, SOE, Op_RegF, 99, F19->as_VMReg()->next()); + reg_def F20 ( SOC, SOE, Op_RegF, 20, F20->as_VMReg() ); // nv + reg_def F20_H( SOC, SOE, Op_RegF, 99, F20->as_VMReg()->next()); + reg_def F21 ( SOC, SOE, Op_RegF, 21, F21->as_VMReg() ); // nv + reg_def F21_H( SOC, SOE, Op_RegF, 99, F21->as_VMReg()->next()); + reg_def F22 ( SOC, SOE, Op_RegF, 22, F22->as_VMReg() ); // nv + reg_def F22_H( SOC, SOE, Op_RegF, 99, F22->as_VMReg()->next()); + reg_def F23 ( SOC, SOE, Op_RegF, 23, F23->as_VMReg() ); // nv + reg_def F23_H( SOC, SOE, Op_RegF, 99, F23->as_VMReg()->next()); + reg_def F24 ( SOC, SOE, Op_RegF, 24, F24->as_VMReg() ); // nv + reg_def F24_H( SOC, SOE, Op_RegF, 99, F24->as_VMReg()->next()); + reg_def F25 ( SOC, SOE, Op_RegF, 25, F25->as_VMReg() ); // nv + reg_def F25_H( SOC, SOE, Op_RegF, 99, F25->as_VMReg()->next()); + reg_def F26 ( SOC, SOE, Op_RegF, 26, F26->as_VMReg() ); // nv + reg_def F26_H( SOC, SOE, Op_RegF, 99, F26->as_VMReg()->next()); + reg_def F27 ( SOC, SOE, Op_RegF, 27, F27->as_VMReg() ); // nv + reg_def F27_H( SOC, SOE, Op_RegF, 99, F27->as_VMReg()->next()); + reg_def F28 ( SOC, SOE, Op_RegF, 28, F28->as_VMReg() ); // nv + reg_def F28_H( SOC, SOE, Op_RegF, 99, F28->as_VMReg()->next()); + reg_def F29 ( SOC, SOE, Op_RegF, 29, F29->as_VMReg() ); // nv + reg_def F29_H( SOC, SOE, Op_RegF, 99, F29->as_VMReg()->next()); + reg_def F30 ( SOC, SOE, Op_RegF, 30, F30->as_VMReg() ); // nv + reg_def F30_H( SOC, SOE, Op_RegF, 99, F30->as_VMReg()->next()); + reg_def F31 ( SOC, SOE, Op_RegF, 31, F31->as_VMReg() ); // nv + reg_def F31_H( SOC, SOE, Op_RegF, 99, F31->as_VMReg()->next()); + +// ---------------------------- +// Special Registers +// ---------------------------- + +// Condition Codes Flag Registers + + // PPC64 has 8 condition code "registers" which are all contained + // in the CR register. + + // types: v = volatile, nv = non-volatile, s = system + reg_def CCR0(SOC, SOC, Op_RegFlags, 0, CCR0->as_VMReg()); // v + reg_def CCR1(SOC, SOC, Op_RegFlags, 1, CCR1->as_VMReg()); // v + reg_def CCR2(SOC, SOC, Op_RegFlags, 2, CCR2->as_VMReg()); // nv + reg_def CCR3(SOC, SOC, Op_RegFlags, 3, CCR3->as_VMReg()); // nv + reg_def CCR4(SOC, SOC, Op_RegFlags, 4, CCR4->as_VMReg()); // nv + reg_def CCR5(SOC, SOC, Op_RegFlags, 5, CCR5->as_VMReg()); // v + reg_def CCR6(SOC, SOC, Op_RegFlags, 6, CCR6->as_VMReg()); // v + reg_def CCR7(SOC, SOC, Op_RegFlags, 7, CCR7->as_VMReg()); // v + + // Special registers of PPC64 + + reg_def SR_XER( SOC, SOC, Op_RegP, 0, SR_XER->as_VMReg()); // v + reg_def SR_LR( SOC, SOC, Op_RegP, 1, SR_LR->as_VMReg()); // v + reg_def SR_CTR( SOC, SOC, Op_RegP, 2, SR_CTR->as_VMReg()); // v + reg_def SR_VRSAVE( SOC, SOC, Op_RegP, 3, SR_VRSAVE->as_VMReg()); // v + reg_def SR_SPEFSCR(SOC, SOC, Op_RegP, 4, SR_SPEFSCR->as_VMReg()); // v + reg_def SR_PPR( SOC, SOC, Op_RegP, 5, SR_PPR->as_VMReg()); // v + + +// ---------------------------- +// Specify priority of register selection within phases of register +// allocation. Highest priority is first. A useful heuristic is to +// give registers a low priority when they are required by machine +// instructions, like EAX and EDX on I486, and choose no-save registers +// before save-on-call, & save-on-call before save-on-entry. Registers +// which participate in fixed calling sequences should come last. +// Registers which are used as pairs must fall on an even boundary. + +// It's worth about 1% on SPEC geomean to get this right. + +// Chunk0, chunk1, and chunk2 form the MachRegisterNumbers enumeration +// in adGlobals_ppc64.hpp which defines the _num values, e.g. +// R3_num. Therefore, R3_num may not be (and in reality is not) +// the same as R3->encoding()! Furthermore, we cannot make any +// assumptions on ordering, e.g. R3_num may be less than R2_num. +// Additionally, the function +// static enum RC rc_class(OptoReg::Name reg ) +// maps a given _num value to its chunk type (except for flags) +// and its current implementation relies on chunk0 and chunk1 having a +// size of 64 each. + +// If you change this allocation class, please have a look at the +// default values for the parameters RoundRobinIntegerRegIntervalStart +// and RoundRobinFloatRegIntervalStart + +alloc_class chunk0 ( + // Chunk0 contains *all* 64 integer registers halves. + + // "non-volatile" registers + R14, R14_H, + R15, R15_H, + R17, R17_H, + R18, R18_H, + R19, R19_H, + R20, R20_H, + R21, R21_H, + R22, R22_H, + R23, R23_H, + R24, R24_H, + R25, R25_H, + R26, R26_H, + R27, R27_H, + R28, R28_H, + R29, R29_H, + R30, R30_H, + R31, R31_H, + + // scratch/special registers + R11, R11_H, + R12, R12_H, + + // argument registers + R10, R10_H, + R9, R9_H, + R8, R8_H, + R7, R7_H, + R6, R6_H, + R5, R5_H, + R4, R4_H, + R3, R3_H, + + // special registers, not available for allocation + R16, R16_H, // R16_thread + R13, R13_H, // system thread id + R2, R2_H, // may be used for TOC + R1, R1_H, // SP + R0, R0_H // R0 (scratch) +); + +// If you change this allocation class, please have a look at the +// default values for the parameters RoundRobinIntegerRegIntervalStart +// and RoundRobinFloatRegIntervalStart + +alloc_class chunk1 ( + // Chunk1 contains *all* 64 floating-point registers halves. + + // scratch register + F0, F0_H, + + // argument registers + F13, F13_H, + F12, F12_H, + F11, F11_H, + F10, F10_H, + F9, F9_H, + F8, F8_H, + F7, F7_H, + F6, F6_H, + F5, F5_H, + F4, F4_H, + F3, F3_H, + F2, F2_H, + F1, F1_H, + + // non-volatile registers + F14, F14_H, + F15, F15_H, + F16, F16_H, + F17, F17_H, + F18, F18_H, + F19, F19_H, + F20, F20_H, + F21, F21_H, + F22, F22_H, + F23, F23_H, + F24, F24_H, + F25, F25_H, + F26, F26_H, + F27, F27_H, + F28, F28_H, + F29, F29_H, + F30, F30_H, + F31, F31_H +); + +alloc_class chunk2 ( + // Chunk2 contains *all* 8 condition code registers. + + CCR0, + CCR1, + CCR2, + CCR3, + CCR4, + CCR5, + CCR6, + CCR7 +); + +alloc_class chunk3 ( + // special registers + // These registers are not allocated, but used for nodes generated by postalloc expand. + SR_XER, + SR_LR, + SR_CTR, + SR_VRSAVE, + SR_SPEFSCR, + SR_PPR +); + +//-------Architecture Description Register Classes----------------------- + +// 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 compiler_method_oop_reg ( as defined in frame section ) +// 2) reg_class interpreter_method_oop_reg ( as defined in frame section ) +// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) +// + +// ---------------------------- +// 32 Bit Register Classes +// ---------------------------- + +// We specify registers twice, once as read/write, and once read-only. +// We use the read-only registers for source operands. With this, we +// can include preset read only registers in this class, as a hard-coded +// '0'-register. (We used to simulate this on ppc.) + +// 32 bit registers that can be read and written i.e. these registers +// can be dest (or src) of normal instructions. +reg_class bits32_reg_rw( +/*R0*/ // R0 +/*R1*/ // SP + R2, // TOC + R3, + R4, + R5, + R6, + R7, + R8, + R9, + R10, + R11, + R12, +/*R13*/ // system thread id + R14, + R15, +/*R16*/ // R16_thread + R17, + R18, + R19, + R20, + R21, + R22, + R23, + R24, + R25, + R26, + R27, + R28, +/*R29*/ // global TOC +/*R30*/ // Narrow Oop Base + R31 +); + +// 32 bit registers that can only be read i.e. these registers can +// only be src of all instructions. +reg_class bits32_reg_ro( +/*R0*/ // R0 +/*R1*/ // SP + R2 // TOC + R3, + R4, + R5, + R6, + R7, + R8, + R9, + R10, + R11, + R12, +/*R13*/ // system thread id + R14, + R15, +/*R16*/ // R16_thread + R17, + R18, + R19, + R20, + R21, + R22, + R23, + R24, + R25, + R26, + R27, + R28, +/*R29*/ +/*R30*/ // Narrow Oop Base + R31 +); + +// Complement-required-in-pipeline operands for narrow oops. +reg_class bits32_reg_ro_not_complement ( +/*R0*/ // R0 + R1, // SP + R2, // TOC + R3, + R4, + R5, + R6, + R7, + R8, + R9, + R10, + R11, + R12, +/*R13,*/ // system thread id + R14, + R15, + R16, // R16_thread + R17, + R18, + R19, + R20, + R21, + R22, +/*R23, + R24, + R25, + R26, + R27, + R28,*/ +/*R29,*/ // TODO: let allocator handle TOC!! +/*R30,*/ + R31 +); + +// Complement-required-in-pipeline operands for narrow oops. +// See 64-bit declaration. +reg_class bits32_reg_ro_complement ( + R23, + R24, + R25, + R26, + R27, + R28 +); + +reg_class rscratch1_bits32_reg(R11); +reg_class rscratch2_bits32_reg(R12); +reg_class rarg1_bits32_reg(R3); +reg_class rarg2_bits32_reg(R4); +reg_class rarg3_bits32_reg(R5); +reg_class rarg4_bits32_reg(R6); + +// ---------------------------- +// 64 Bit Register Classes +// ---------------------------- +// 64-bit build means 64-bit pointers means hi/lo pairs + +reg_class rscratch1_bits64_reg(R11_H, R11); +reg_class rscratch2_bits64_reg(R12_H, R12); +reg_class rarg1_bits64_reg(R3_H, R3); +reg_class rarg2_bits64_reg(R4_H, R4); +reg_class rarg3_bits64_reg(R5_H, R5); +reg_class rarg4_bits64_reg(R6_H, R6); +// Thread register, 'written' by tlsLoadP, see there. +reg_class thread_bits64_reg(R16_H, R16); + +reg_class r19_bits64_reg(R19_H, R19); + +// 64 bit registers that can be read and written i.e. these registers +// can be dest (or src) of normal instructions. +reg_class bits64_reg_rw( +/*R0_H, R0*/ // R0 +/*R1_H, R1*/ // SP + R2_H, R2, // TOC + R3_H, R3, + R4_H, R4, + R5_H, R5, + R6_H, R6, + R7_H, R7, + R8_H, R8, + R9_H, R9, + R10_H, R10, + R11_H, R11, + R12_H, R12, +/*R13_H, R13*/ // system thread id + R14_H, R14, + R15_H, R15, +/*R16_H, R16*/ // R16_thread + R17_H, R17, + R18_H, R18, + R19_H, R19, + R20_H, R20, + R21_H, R21, + R22_H, R22, + R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28, +/*R29_H, R29*/ +/*R30_H, R30*/ + R31_H, R31 +); + +// 64 bit registers used excluding r2, r11 and r12 +// Used to hold the TOC to avoid collisions with expanded LeafCall which uses +// r2, r11 and r12 internally. +reg_class bits64_reg_leaf_call( +/*R0_H, R0*/ // R0 +/*R1_H, R1*/ // SP +/*R2_H, R2*/ // TOC + R3_H, R3, + R4_H, R4, + R5_H, R5, + R6_H, R6, + R7_H, R7, + R8_H, R8, + R9_H, R9, + R10_H, R10, +/*R11_H, R11*/ +/*R12_H, R12*/ +/*R13_H, R13*/ // system thread id + R14_H, R14, + R15_H, R15, +/*R16_H, R16*/ // R16_thread + R17_H, R17, + R18_H, R18, + R19_H, R19, + R20_H, R20, + R21_H, R21, + R22_H, R22, + R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28, +/*R29_H, R29*/ +/*R30_H, R30*/ + R31_H, R31 +); + +// 64 bit registers used excluding r19. +// Used to hold the TOC to avoid collisions with expanded DynamicCall +// which uses r19 as inline cache internally and expanded LeafCall which uses +// r2, r11 and r12 internally. +reg_class bits64_constant_table_base( +/*R0_H, R0*/ // R0 +/*R1_H, R1*/ // SP +/*R2_H, R2*/ // TOC + R3_H, R3, + R4_H, R4, + R5_H, R5, + R6_H, R6, + R7_H, R7, + R8_H, R8, + R9_H, R9, + R10_H, R10, +/*R11_H, R11*/ +/*R12_H, R12*/ +/*R13_H, R13*/ // system thread id + R14_H, R14, + R15_H, R15, +/*R16_H, R16*/ // R16_thread + R17_H, R17, + R18_H, R18, +/*R19_H, R19*/ + R20_H, R20, + R21_H, R21, + R22_H, R22, + R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28, +/*R29_H, R29*/ +/*R30_H, R30*/ + R31_H, R31 +); + +// 64 bit registers that can only be read i.e. these registers can +// only be src of all instructions. +reg_class bits64_reg_ro( +/*R0_H, R0*/ // R0 + R1_H, R1, + R2_H, R2, // TOC + R3_H, R3, + R4_H, R4, + R5_H, R5, + R6_H, R6, + R7_H, R7, + R8_H, R8, + R9_H, R9, + R10_H, R10, + R11_H, R11, + R12_H, R12, +/*R13_H, R13*/ // system thread id + R14_H, R14, + R15_H, R15, + R16_H, R16, // R16_thread + R17_H, R17, + R18_H, R18, + R19_H, R19, + R20_H, R20, + R21_H, R21, + R22_H, R22, + R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28, +/*R29_H, R29*/ // TODO: let allocator handle TOC!! +/*R30_H, R30,*/ + R31_H, R31 +); + +// Complement-required-in-pipeline operands. +reg_class bits64_reg_ro_not_complement ( +/*R0_H, R0*/ // R0 + R1_H, R1, // SP + R2_H, R2, // TOC + R3_H, R3, + R4_H, R4, + R5_H, R5, + R6_H, R6, + R7_H, R7, + R8_H, R8, + R9_H, R9, + R10_H, R10, + R11_H, R11, + R12_H, R12, +/*R13_H, R13*/ // system thread id + R14_H, R14, + R15_H, R15, + R16_H, R16, // R16_thread + R17_H, R17, + R18_H, R18, + R19_H, R19, + R20_H, R20, + R21_H, R21, + R22_H, R22, +/*R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28,*/ +/*R29_H, R29*/ // TODO: let allocator handle TOC!! +/*R30_H, R30,*/ + R31_H, R31 +); + +// Complement-required-in-pipeline operands. +// This register mask is used for the trap instructions that implement +// the null checks on AIX. The trap instruction first computes the +// complement of the value it shall trap on. Because of this, the +// instruction can not be scheduled in the same cycle as an other +// instruction reading the normal value of the same register. So we +// force the value to check into 'bits64_reg_ro_not_complement' +// and then copy it to 'bits64_reg_ro_complement' for the trap. +reg_class bits64_reg_ro_complement ( + R23_H, R23, + R24_H, R24, + R25_H, R25, + R26_H, R26, + R27_H, R27, + R28_H, R28 +); + + +// ---------------------------- +// Special Class for Condition Code Flags Register + +reg_class int_flags( +/*CCR0*/ // scratch +/*CCR1*/ // scratch +/*CCR2*/ // nv! +/*CCR3*/ // nv! +/*CCR4*/ // nv! + CCR5, + CCR6, + CCR7 +); + +reg_class int_flags_CR0(CCR0); +reg_class int_flags_CR1(CCR1); +reg_class int_flags_CR6(CCR6); +reg_class ctr_reg(SR_CTR); + +// ---------------------------- +// Float Register Classes +// ---------------------------- + +reg_class flt_reg( +/*F0*/ // scratch + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, // nv! + F15, // nv! + F16, // nv! + F17, // nv! + F18, // nv! + F19, // nv! + F20, // nv! + F21, // nv! + F22, // nv! + F23, // nv! + F24, // nv! + F25, // nv! + F26, // nv! + F27, // nv! + F28, // nv! + F29, // nv! + F30, // nv! + F31 // nv! +); + +// Double precision float registers have virtual `high halves' that +// are needed by the allocator. +reg_class dbl_reg( +/*F0, F0_H*/ // scratch + F1, F1_H, + F2, F2_H, + F3, F3_H, + F4, F4_H, + F5, F5_H, + F6, F6_H, + F7, F7_H, + F8, F8_H, + F9, F9_H, + F10, F10_H, + F11, F11_H, + F12, F12_H, + F13, F13_H, + F14, F14_H, // nv! + F15, F15_H, // nv! + F16, F16_H, // nv! + F17, F17_H, // nv! + F18, F18_H, // nv! + F19, F19_H, // nv! + F20, F20_H, // nv! + F21, F21_H, // nv! + F22, F22_H, // nv! + F23, F23_H, // nv! + F24, F24_H, // nv! + F25, F25_H, // nv! + F26, F26_H, // nv! + F27, F27_H, // nv! + F28, F28_H, // nv! + F29, F29_H, // nv! + F30, F30_H, // nv! + F31, F31_H // nv! +); + + %} + +//----------DEFINITION BLOCK--------------------------------------------------- +// Define name --> value mappings to inform the ADLC of an integer valued name +// Current support includes integer values in the range [0, 0x7FFFFFFF] +// Format: +// int_def ( , ); +// Generated Code in ad_.hpp +// #define () +// // value == +// Generated code in ad_.cpp adlc_verification() +// assert( == , "Expect () to equal "); +// +definitions %{ + // The default cost (of an ALU instruction). + int_def DEFAULT_COST_LOW ( 30, 30); + int_def DEFAULT_COST ( 100, 100); + int_def HUGE_COST (1000000, 1000000); + + // Memory refs + int_def MEMORY_REF_COST_LOW ( 200, DEFAULT_COST * 2); + int_def MEMORY_REF_COST ( 300, DEFAULT_COST * 3); + + // Branches are even more expensive. + int_def BRANCH_COST ( 900, DEFAULT_COST * 9); + int_def CALL_COST ( 1300, DEFAULT_COST * 13); +%} + + +//----------SOURCE BLOCK------------------------------------------------------- +// This is a block of C++ code which provides values, functions, and +// definitions necessary in the rest of the architecture description. +source_hpp %{ + // Returns true if Node n is followed by a MemBar node that + // will do an acquire. If so, this node must not do the acquire + // operation. + bool followed_by_acquire(const Node *n); +%} + +source %{ + +// Optimize load-acquire. +// +// Check if acquire is unnecessary due to following operation that does +// acquire anyways. +// Walk the pattern: +// +// n: Load.acq +// | +// MemBarAcquire +// | | +// Proj(ctrl) Proj(mem) +// | | +// MemBarRelease/Volatile +// +bool followed_by_acquire(const Node *load) { + assert(load->is_Load(), "So far implemented only for loads."); + + // Find MemBarAcquire. + const Node *mba = NULL; + for (DUIterator_Fast imax, i = load->fast_outs(imax); i < imax; i++) { + const Node *out = load->fast_out(i); + if (out->Opcode() == Op_MemBarAcquire) { + if (out->in(0) == load) continue; // Skip control edge, membar should be found via precedence edge. + mba = out; + break; + } + } + if (!mba) return false; + + // Find following MemBar node. + // + // The following node must be reachable by control AND memory + // edge to assure no other operations are in between the two nodes. + // + // So first get the Proj node, mem_proj, to use it to iterate forward. + Node *mem_proj = NULL; + for (DUIterator_Fast imax, i = mba->fast_outs(imax); i < imax; i++) { + mem_proj = mba->fast_out(i); // Throw out-of-bounds if proj not found + assert(mem_proj->is_Proj(), "only projections here"); + ProjNode *proj = mem_proj->as_Proj(); + if (proj->_con == TypeFunc::Memory && + !Compile::current()->node_arena()->contains(mem_proj)) // Unmatched old-space only + break; + } + assert(mem_proj->as_Proj()->_con == TypeFunc::Memory, "Graph broken"); + + // Search MemBar behind Proj. If there are other memory operations + // behind the Proj we lost. + for (DUIterator_Fast jmax, j = mem_proj->fast_outs(jmax); j < jmax; j++) { + Node *x = mem_proj->fast_out(j); + // Proj might have an edge to a store or load node which precedes the membar. + if (x->is_Mem()) return false; + + // On PPC64 release and volatile are implemented by an instruction + // that also has acquire semantics. I.e. there is no need for an + // acquire before these. + int xop = x->Opcode(); + if (xop == Op_MemBarRelease || xop == Op_MemBarVolatile) { + // Make sure we're not missing Call/Phi/MergeMem by checking + // control edges. The control edge must directly lead back + // to the MemBarAcquire + Node *ctrl_proj = x->in(0); + if (ctrl_proj->is_Proj() && ctrl_proj->in(0) == mba) { + return true; + } + } + } + + return false; +} + +#define __ _masm. + +// Tertiary op of a LoadP or StoreP encoding. +#define REGP_OP true + +// **************************************************************************** + +// REQUIRED FUNCTIONALITY + +// !!!!! Special hack to get all type of calls to specify the byte offset +// from the start of the call to the point where the return address +// will point. + +// PPC port: Removed use of lazy constant construct. + +int MachCallStaticJavaNode::ret_addr_offset() { + // It's only a single branch-and-link instruction. + return 4; +} + +int MachCallDynamicJavaNode::ret_addr_offset() { + // Offset is 4 with postalloc expanded calls (bl is one instruction). We use + // postalloc expanded calls if we use inline caches and do not update method data. + if (UseInlineCaches) + return 4; + + int vtable_index = this->_vtable_index; + if (vtable_index < 0) { + // Must be invalid_vtable_index, not nonvirtual_vtable_index. + assert(vtable_index == Method::invalid_vtable_index, "correct sentinel value"); + return 12; + } else { + assert(!UseInlineCaches, "expect vtable calls only if not using ICs"); + return 24; + } +} + +int MachCallRuntimeNode::ret_addr_offset() { + return 40; +} + +//============================================================================= + +// condition code conversions + +static int cc_to_boint(int cc) { + return Assembler::bcondCRbiIs0 | (cc & 8); +} + +static int cc_to_inverse_boint(int cc) { + return Assembler::bcondCRbiIs0 | (8-(cc & 8)); +} + +static int cc_to_biint(int cc, int flags_reg) { + return (flags_reg << 2) | (cc & 3); +} + +//============================================================================= + +// Compute padding required for nodes which need alignment. The padding +// is the number of bytes (not instructions) which will be inserted before +// the instruction. The padding must match the size of a NOP instruction. + +int string_indexOf_imm1_charNode::compute_padding(int current_offset) const { + return (3*4-current_offset)&31; +} + +int string_indexOf_imm1Node::compute_padding(int current_offset) const { + return (2*4-current_offset)&31; +} + +int string_indexOf_immNode::compute_padding(int current_offset) const { + return (3*4-current_offset)&31; +} + +int string_indexOfNode::compute_padding(int current_offset) const { + return (1*4-current_offset)&31; +} + +int string_compareNode::compute_padding(int current_offset) const { + return (4*4-current_offset)&31; +} + +int string_equals_immNode::compute_padding(int current_offset) const { + if (opnd_array(3)->constant() < 16) return 0; // Don't insert nops for short version (loop completely unrolled). + return (2*4-current_offset)&31; +} + +int string_equalsNode::compute_padding(int current_offset) const { + return (7*4-current_offset)&31; +} + +int inlineCallClearArrayNode::compute_padding(int current_offset) const { + return (2*4-current_offset)&31; +} + +//============================================================================= + +// Indicate if the safepoint node needs the polling page as an input. +bool SafePointNode::needs_polling_address_input() { + // The address is loaded from thread by a seperate node. + return true; +} + +//============================================================================= + +// Emit an interrupt that is caught by the debugger (for debugging compiler). +void emit_break(CodeBuffer &cbuf) { + MacroAssembler _masm(&cbuf); + __ illtrap(); +} + +#ifndef PRODUCT +void MachBreakpointNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + st->print("BREAKPOINT"); +} +#endif + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + emit_break(cbuf); +} + +uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { + return MachNode::size(ra_); +} + +//============================================================================= + +void emit_nop(CodeBuffer &cbuf) { + MacroAssembler _masm(&cbuf); + __ nop(); +} + +static inline void emit_long(CodeBuffer &cbuf, int value) { + *((int*)(cbuf.insts_end())) = value; + cbuf.set_insts_end(cbuf.insts_end() + BytesPerInstWord); +} + +//============================================================================= + +// Emit a trampoline stub for a call to a target which is too far away. +// +// code sequences: +// +// call-site: +// branch-and-link to or +// +// Related trampoline stub for this call-site in the stub section: +// load the call target from the constant pool +// branch via CTR (LR/link still points to the call-site above) + +const uint trampoline_stub_size = 6 * BytesPerInstWord; + +void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) { + // Start the stub. + address stub = __ start_a_stub(Compile::MAX_stubs_size/2); + if (stub == NULL) { + Compile::current()->env()->record_out_of_memory_failure(); + return; + } + + // For java_to_interp stubs we use R11_scratch1 as scratch register + // and in call trampoline stubs we use R12_scratch2. This way we + // can distinguish them (see is_NativeCallTrampolineStub_at()). + Register reg_scratch = R12_scratch2; + + // Create a trampoline stub relocation which relates this trampoline stub + // with the call instruction at insts_call_instruction_offset in the + // instructions code-section. + __ relocate(trampoline_stub_Relocation::spec(__ code()->insts()->start() + insts_call_instruction_offset)); + const int stub_start_offset = __ offset(); + + // Now, create the trampoline stub's code: + // - load the TOC + // - load the call target from the constant pool + // - call + __ calculate_address_from_global_toc(reg_scratch, __ method_toc()); + __ ld_largeoffset_unchecked(reg_scratch, destination_toc_offset, reg_scratch, false); + __ mtctr(reg_scratch); + __ bctr(); + + const address stub_start_addr = __ addr_at(stub_start_offset); + + // FIXME: Assert that the trampoline stub can be identified and patched. + + // Assert that the encoded destination_toc_offset can be identified and that it is correct. + assert(destination_toc_offset == NativeCallTrampolineStub_at(stub_start_addr)->destination_toc_offset(), + "encoded offset into the constant pool must match"); + // Trampoline_stub_size should be good. + assert((uint)(__ offset() - stub_start_offset) <= trampoline_stub_size, "should be good size"); + assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline"); + + // End the stub. + __ end_a_stub(); +} + +// Size of trampoline stub, this doesn't need to be accurate but it must +// be larger or equal to the real size of the stub. +// Used for optimization in Compile::Shorten_branches. +uint size_call_trampoline() { + return trampoline_stub_size; +} + +// Number of relocation entries needed by trampoline stub. +// Used for optimization in Compile::Shorten_branches. +uint reloc_call_trampoline() { + return 5; +} + +//============================================================================= + +// Emit an inline branch-and-link call and a related trampoline stub. +// +// code sequences: +// +// call-site: +// branch-and-link to or +// +// Related trampoline stub for this call-site in the stub section: +// load the call target from the constant pool +// branch via CTR (LR/link still points to the call-site above) +// + +typedef struct { + int insts_call_instruction_offset; + int ret_addr_offset; +} EmitCallOffsets; + +// Emit a branch-and-link instruction that branches to a trampoline. +// - Remember the offset of the branch-and-link instruction. +// - Add a relocation at the branch-and-link instruction. +// - Emit a branch-and-link. +// - Remember the return pc offset. +EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address entry_point, relocInfo::relocType rtype) { + EmitCallOffsets offsets = { -1, -1 }; + const int start_offset = __ offset(); + offsets.insts_call_instruction_offset = __ offset(); + + // No entry point given, use the current pc. + if (entry_point == NULL) entry_point = __ pc(); + + if (!Compile::current()->in_scratch_emit_size()) { + // Put the entry point as a constant into the constant pool. + const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none); + const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); + + // Emit the trampoline stub which will be related to the branch-and-link below. + emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset); + __ relocate(rtype); + } + + // Note: At this point we do not have the address of the trampoline + // stub, and the entry point might be too far away for bl, so __ pc() + // serves as dummy and the bl will be patched later. + __ bl((address) __ pc()); + + offsets.ret_addr_offset = __ offset() - start_offset; + + return offsets; +} + +//============================================================================= + +// Factory for creating loadConL* nodes for large/small constant pool. + +static inline jlong replicate_immF(float con) { + // Replicate float con 2 times and pack into vector. + int val = *((int*)&con); + jlong lval = val; + lval = (lval << 32) | (lval & 0xFFFFFFFFl); + return lval; +} + +//============================================================================= + +const RegMask& MachConstantBaseNode::_out_RegMask = BITS64_CONSTANT_TABLE_BASE_mask(); +int Compile::ConstantTable::calculate_table_base_offset() const { + return 0; // absolute addressing, no offset +} + +bool MachConstantBaseNode::requires_postalloc_expand() const { return true; } +void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { + Compile *C = ra_->C; + + iRegPdstOper *op_dst = new (C) iRegPdstOper(); + MachNode *m1 = new (C) loadToc_hiNode(); + MachNode *m2 = new (C) loadToc_loNode(); + + m1->add_req(NULL); + m2->add_req(NULL, m1); + m1->_opnds[0] = op_dst; + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_dst; + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m1); + nodes->push(m2); +} + +void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + // Is postalloc expanded. + ShouldNotReachHere(); +} + +uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { + return 0; +} + +#ifndef PRODUCT +void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { + st->print("-- \t// MachConstantBaseNode (empty encoding)"); +} +#endif + +//============================================================================= + +#ifndef PRODUCT +void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + Compile* C = ra_->C; + const long framesize = C->frame_slots() << LogBytesPerInt; + + st->print("PROLOG\n\t"); + if (C->need_stack_bang(framesize)) { + st->print("stack_overflow_check\n\t"); + } + + if (!false /* TODO: PPC port C->is_frameless_method()*/) { + st->print("save return pc\n\t"); + st->print("push frame %d\n\t", -framesize); + } +} +#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; + MacroAssembler _masm(&cbuf); + + const long framesize = ((long)C->frame_slots()) << LogBytesPerInt; + assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); + + const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; + + const Register return_pc = R20; // Must match return_addr() in frame section. + const Register callers_sp = R21; + const Register push_frame_temp = R22; + const Register toc_temp = R23; + assert_different_registers(R11, return_pc, callers_sp, push_frame_temp, toc_temp); + + if (method_is_frameless) { + // 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(); + } else { + // Get return pc. + ___(mflr) mflr(return_pc); + } + + // Calls to C2R adapters often do not accept exceptional returns. + // We require that their callers must bang for them. But be + // careful, because some VM calls (such as call site linkage) can + // use several kilobytes of stack. But the stack safety zone should + // account for that. See bugs 4446381, 4468289, 4497237. + if (C->need_stack_bang(framesize) && UseStackBanging) { + // Unfortunately we cannot use the function provided in + // assembler.cpp as we have to emulate the pipes. So I had to + // insert the code of generate_stack_overflow_check(), see + // assembler.cpp for some illuminative comments. + const int page_size = os::vm_page_size(); + int bang_end = StackShadowPages*page_size; + + // This is how far the previous frame's stack banging extended. + const int bang_end_safe = bang_end; + + if (framesize > page_size) { + bang_end += framesize; + } + + int bang_offset = bang_end_safe; + + while (bang_offset <= bang_end) { + // Need at least one stack bang at end of shadow zone. + + // Again I had to copy code, this time from assembler_ppc64.cpp, + // bang_stack_with_offset - see there for comments. + + // Stack grows down, caller passes positive offset. + assert(bang_offset > 0, "must bang with positive offset"); + + long stdoffset = -bang_offset; + + 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); + } else { + ___(std) std(R0, (int)(signed short)stdoffset, R1_SP); + } + } else if (Assembler::is_simm(stdoffset, 31)) { + // Use largeoffset calculations for addis & ld/std. + const int hi = MacroAssembler::largeoffset_si16_si16_hi(stdoffset); + const int lo = MacroAssembler::largeoffset_si16_si16_lo(stdoffset); + + Register tmp = R11; + ___(addis) addis(tmp, R1_SP, hi); + if (UseLoadInstructionsForStackBangingPPC64) { + ___(ld) ld(R0, lo, tmp); + } else { + ___(std) std(R0, lo, tmp); + } + } else { + ShouldNotReachHere(); + } + + bang_offset += page_size; + } + // R11 trashed + } // C->need_stack_bang(framesize) && UseStackBanging + + unsigned int bytes = (unsigned int)framesize; + 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)(-(_abi(lr) + offset)), 16) && + !(false /* ConstantsALot TODO: PPC port*/)) { + ___(or) mr(callers_sp, R1_SP); + ___(addi) addi(R1_SP, R1_SP, -offset); + ___stop; // Emulator won't recognize dependency. + ___(std) std(return_pc, _abi(lr) + offset, R1_SP); + ___(std) std(callers_sp, 0, R1_SP); + return; + } + + if (!method_is_frameless) { + // Get callers sp. + ___(or) mr(callers_sp, R1_SP); + + // Push method's frame, modifies SP. + assert(Assembler::is_uimm(framesize, 32U), "wrong type"); + // The ABI is already accounted for in 'framesize' via the + // 'out_preserve' area. + 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); + } 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)); + + ___(stdux) stdux(R1_SP, R1_SP, tmp); + } + } +#if 0 // TODO: PPC port + // For testing large constant pools, emit a lot of constants to constant pool. + // "Randomize" const_size. + if (ConstantsALot) { + const int num_consts = const_size(); + for (int i = 0; i < num_consts; i++) { + __ long_constant(0xB0B5B00BBABE); + } + } +#endif + if (!method_is_frameless) { + // Save return pc. + ___(std) std(return_pc, _abi(lr), callers_sp); + } +} +#undef ___ +#undef ___stop + +uint MachPrologNode::size(PhaseRegAlloc *ra_) const { + // Variable size. determine dynamically. + return MachNode::size(ra_); +} + +int MachPrologNode::reloc() const { + // Return number of relocatable values contained in this instruction. + return 1; // 1 reloc entry for load_const(toc). +} + +//============================================================================= + +#ifndef PRODUCT +void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + Compile* C = ra_->C; + + st->print("EPILOG\n\t"); + st->print("restore return pc\n\t"); + st->print("pop frame\n\t"); + + if (do_polling() && C->is_method_compilation()) { + st->print("touch polling page\n\t"); + } +} +#endif + +void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + Compile* C = ra_->C; + MacroAssembler _masm(&cbuf); + + const long framesize = ((long)C->frame_slots()) << LogBytesPerInt; + assert(framesize >= 0, "negative frame-size?"); + + const bool method_needs_polling = do_polling() && C->is_method_compilation(); + const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; + const Register return_pc = R11; + const Register polling_page = R12; + + if (!method_is_frameless) { + // Restore return pc relative to callers' sp. + __ ld(return_pc, ((int)framesize) + _abi(lr), R1_SP); + } + + if (method_needs_polling) { + if (LoadPollAddressFromThread) { + // TODO: PPC port __ ld(polling_page, in_bytes(JavaThread::poll_address_offset()), R16_thread); + Unimplemented(); + } else { + __ load_const_optimized(polling_page, (long)(address) os::get_polling_page()); // TODO: PPC port: get_standard_polling_page() + } + } + + if (!method_is_frameless) { + // Move return pc to LR. + __ mtlr(return_pc); + // Pop frame (fixed frame-size). + __ addi(R1_SP, R1_SP, (int)framesize); + } + + if (method_needs_polling) { + // We need to mark the code position where the load from the safepoint + // polling page was emitted as relocInfo::poll_return_type here. + __ relocate(relocInfo::poll_return_type); + __ load_from_polling_page(polling_page); + } +} + +uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { + // Variable size. Determine dynamically. + return MachNode::size(ra_); +} + +int MachEpilogNode::reloc() const { + // Return number of relocatable values contained in this instruction. + return 1; // 1 for load_from_polling_page. +} + +const Pipeline * MachEpilogNode::pipeline() const { + return MachNode::pipeline_class(); +} + +// This method seems to be obsolete. It is declared in machnode.hpp +// and defined in all *.ad files, but it is never called. Should we +// get rid of it? +int MachEpilogNode::safepoint_offset() const { + assert(do_polling(), "no return for this epilog node"); + return 0; +} + +#if 0 // TODO: PPC port +void MachLoadPollAddrLateNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + 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 or +// rc_stack. +enum RC { rc_bad, rc_int, rc_float, rc_stack }; + +static enum RC rc_class(OptoReg::Name reg) { + // Return the register class for the given register. The given register + // reg is a _num value, which is an index into the MachRegisterNumbers + // enumeration in adGlobals_ppc64.hpp. + + if (reg == OptoReg::Bad) return rc_bad; + + // We have 64 integer register halves, starting at index 0. + if (reg < 64) return rc_int; + + // We have 64 floating-point register halves, starting at index 64. + if (reg < 64+64) return rc_float; + + // Between float regs & stack are the flags regs. + assert(OptoReg::is_stack(reg), "blow up if spilling flags"); + + return rc_stack; +} + +static int ld_st_helper(CodeBuffer *cbuf, const char *op_str, uint opcode, int reg, int offset, + bool do_print, Compile* C, outputStream *st) { + + assert(opcode == Assembler::LD_OPCODE || + opcode == Assembler::STD_OPCODE || + opcode == Assembler::LWZ_OPCODE || + opcode == Assembler::STW_OPCODE || + opcode == Assembler::LFD_OPCODE || + opcode == Assembler::STFD_OPCODE || + opcode == Assembler::LFS_OPCODE || + opcode == Assembler::STFS_OPCODE, + "opcode not supported"); + + if (cbuf) { + int d = + (Assembler::LD_OPCODE == opcode || Assembler::STD_OPCODE == opcode) ? + Assembler::ds(offset+0 /* TODO: PPC port C->frame_slots_sp_bias_in_bytes()*/) + : Assembler::d1(offset+0 /* TODO: PPC port C->frame_slots_sp_bias_in_bytes()*/); // Makes no difference in opt build. + emit_long(*cbuf, opcode | Assembler::rt(Matcher::_regEncode[reg]) | d | Assembler::ra(R1_SP)); + } +#ifndef PRODUCT + else if (do_print) { + st->print("%-7s %s, [R1_SP + #%d+%d] \t// spill copy", + op_str, + Matcher::regName[reg], + offset, 0 /* TODO: PPC port C->frame_slots_sp_bias_in_bytes()*/); + } +#endif + return 4; // size +} + +uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream *st) const { + Compile* C = ra_->C; + + // Get registers to move. + OptoReg::Name src_hi = ra_->get_reg_second(in(1)); + OptoReg::Name src_lo = ra_->get_reg_first(in(1)); + OptoReg::Name dst_hi = ra_->get_reg_second(this); + OptoReg::Name dst_lo = ra_->get_reg_first(this); + + enum RC src_hi_rc = rc_class(src_hi); + enum RC src_lo_rc = rc_class(src_lo); + enum RC dst_hi_rc = rc_class(dst_hi); + enum RC dst_lo_rc = rc_class(dst_lo); + + assert(src_lo != OptoReg::Bad && dst_lo != OptoReg::Bad, "must move at least 1 register"); + if (src_hi != OptoReg::Bad) + assert((src_lo&1)==0 && src_lo+1==src_hi && + (dst_lo&1)==0 && dst_lo+1==dst_hi, + "expected aligned-adjacent pairs"); + // Generate spill code! + int size = 0; + + if (src_lo == dst_lo && src_hi == dst_hi) + return size; // Self copy, no move. + + // -------------------------------------- + // Memory->Memory Spill. Use R0 to hold the value. + if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { + int src_offset = ra_->reg2offset(src_lo); + int dst_offset = ra_->reg2offset(dst_lo); + if (src_hi != OptoReg::Bad) { + assert(src_hi_rc==rc_stack && dst_hi_rc==rc_stack, + "expected same type of move for high parts"); + size += ld_st_helper(cbuf, "LD ", Assembler::LD_OPCODE, R0_num, src_offset, !do_size, C, st); + if (!cbuf && !do_size) st->print("\n\t"); + size += ld_st_helper(cbuf, "STD ", Assembler::STD_OPCODE, R0_num, dst_offset, !do_size, C, st); + } else { + size += ld_st_helper(cbuf, "LWZ ", Assembler::LWZ_OPCODE, R0_num, src_offset, !do_size, C, st); + if (!cbuf && !do_size) st->print("\n\t"); + size += ld_st_helper(cbuf, "STW ", Assembler::STW_OPCODE, R0_num, dst_offset, !do_size, C, st); + } + return size; + } + + // -------------------------------------- + // 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]); + size = (Rsrc != Rdst) ? 4 : 0; + + if (cbuf) { + MacroAssembler _masm(cbuf); + if (size) { + __ mr(Rdst, Rsrc); + } + } +#ifndef PRODUCT + else if (!do_size) { + if (size) { + st->print("%-7s %s, %s \t// spill copy", "MR", Matcher::regName[dst_lo], Matcher::regName[src_lo]); + } else { + st->print("%-7s %s, %s \t// spill copy", "MR-NOP", Matcher::regName[dst_lo], Matcher::regName[src_lo]); + } + } +#endif + return size; + } + + // Check for integer store. + if (src_lo_rc == rc_int && dst_lo_rc == rc_stack) { + int dst_offset = ra_->reg2offset(dst_lo); + if (src_hi != OptoReg::Bad) { + assert(src_hi_rc==rc_int && dst_hi_rc==rc_stack, + "expected same type of move for high parts"); + size += ld_st_helper(cbuf, "STD ", Assembler::STD_OPCODE, src_lo, dst_offset, !do_size, C, st); + } else { + size += ld_st_helper(cbuf, "STW ", Assembler::STW_OPCODE, src_lo, dst_offset, !do_size, C, st); + } + return size; + } + + // Check for integer load. + if (dst_lo_rc == rc_int && src_lo_rc == rc_stack) { + int src_offset = ra_->reg2offset(src_lo); + if (src_hi != OptoReg::Bad) { + assert(dst_hi_rc==rc_int && src_hi_rc==rc_stack, + "expected same type of move for high parts"); + size += ld_st_helper(cbuf, "LD ", Assembler::LD_OPCODE, dst_lo, src_offset, !do_size, C, st); + } else { + size += ld_st_helper(cbuf, "LWZ ", Assembler::LWZ_OPCODE, dst_lo, src_offset, !do_size, C, st); + } + return size; + } + + // Check for float reg-reg copy. + if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { + if (cbuf) { + MacroAssembler _masm(cbuf); + FloatRegister Rsrc = as_FloatRegister(Matcher::_regEncode[src_lo]); + FloatRegister Rdst = as_FloatRegister(Matcher::_regEncode[dst_lo]); + __ fmr(Rdst, Rsrc); + } +#ifndef PRODUCT + else if (!do_size) { + st->print("%-7s %s, %s \t// spill copy", "FMR", Matcher::regName[dst_lo], Matcher::regName[src_lo]); + } +#endif + return 4; + } + + // Check for float store. + if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { + int dst_offset = ra_->reg2offset(dst_lo); + if (src_hi != OptoReg::Bad) { + assert(src_hi_rc==rc_float && dst_hi_rc==rc_stack, + "expected same type of move for high parts"); + size += ld_st_helper(cbuf, "STFD", Assembler::STFD_OPCODE, src_lo, dst_offset, !do_size, C, st); + } else { + size += ld_st_helper(cbuf, "STFS", Assembler::STFS_OPCODE, src_lo, dst_offset, !do_size, C, st); + } + return size; + } + + // Check for float load. + if (dst_lo_rc == rc_float && src_lo_rc == rc_stack) { + int src_offset = ra_->reg2offset(src_lo); + if (src_hi != OptoReg::Bad) { + assert(dst_hi_rc==rc_float && src_hi_rc==rc_stack, + "expected same type of move for high parts"); + size += ld_st_helper(cbuf, "LFD ", Assembler::LFD_OPCODE, dst_lo, src_offset, !do_size, C, st); + } else { + size += ld_st_helper(cbuf, "LFS ", Assembler::LFS_OPCODE, dst_lo, src_offset, !do_size, C, st); + } + return size; + } + + // -------------------------------------------------------------------- + // Check for hi bits still needing moving. Only happens for misaligned + // arguments to native calls. + if (src_hi == dst_hi) + return size; // Self copy; no move. + + assert(src_hi_rc != rc_bad && dst_hi_rc != rc_bad, "src_hi & dst_hi cannot be Bad"); + ShouldNotReachHere(); // Unimplemented + return 0; +} + +#ifndef PRODUCT +void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + if (!ra_) + st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx); + else + implementation(NULL, ra_, false, st); +} +#endif + +void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + implementation(&cbuf, ra_, false, NULL); +} + +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); +} +#endif + +void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const { + MacroAssembler _masm(&cbuf); + // _count contains the number of nops needed for padding. + for (int i = 0; i < _count; i++) { + __ nop(); + } +} + +uint MachNopNode::size(PhaseRegAlloc *ra_) const { + return _count * 4; +} + +#ifndef PRODUCT +void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + int reg = ra_->get_reg_first(this); + st->print("ADDI %s, SP, %d \t// box node", Matcher::regName[reg], offset); +} +#endif + +void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + MacroAssembler _masm(&cbuf); + + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + int reg = ra_->get_encode(this); + + if (Assembler::is_simm(offset, 16)) { + __ addi(as_Register(reg), R1, offset); + } else { + ShouldNotReachHere(); + } +} + +uint BoxLockNode::size(PhaseRegAlloc *ra_) const { + // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_). + return 4; +} + +#ifndef PRODUCT +void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *st) const { + st->print_cr("---- MachUEPNode ----"); + st->print_cr("..."); +} +#endif + +void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + // This is the unverified entry point. + MacroAssembler _masm(&cbuf); + + // Inline_cache contains a klass. + Register ic_klass = as_Register(Matcher::inline_cache_reg_encode()); + Register receiver_klass = R0; // tmp + + assert_different_registers(ic_klass, receiver_klass, R11_scratch1, R3_ARG1); + assert(R11_scratch1 == R11, "need prologue scratch register"); + + // Check for NULL argument if we don't have implicit null checks. + if (!ImplicitNullChecks || !os::zero_page_read_protected()) { + if (TrapBasedNullChecks) { + __ trap_null_check(R3_ARG1); + } else { + Label valid; + __ cmpdi(CCR0, R3_ARG1, 0); + __ bne_predict_taken(CCR0, valid); + // We have a null argument, branch to ic_miss_stub. + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + __ bind(valid); + } + } + // Assume argument is not NULL, load klass from receiver. + __ load_klass(receiver_klass, R3_ARG1); + + if (TrapBasedICMissChecks) { + __ trap_ic_miss_check(receiver_klass, ic_klass); + } else { + Label valid; + __ cmpd(CCR0, receiver_klass, ic_klass); + __ beq_predict_taken(CCR0, valid); + // We have an unexpected klass, branch to ic_miss_stub. + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), + relocInfo::runtime_call_type); + __ bind(valid); + } + + // 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_); +} + +//============================================================================= + +uint size_exception_handler() { + // The exception_handler is a b64_patchable. + return MacroAssembler::b64_patchable_size; +} + +uint size_deopt_handler() { + // The deopt_handler is a bl64_patchable. + return MacroAssembler::bl64_patchable_size; +} + +int emit_exception_handler(CodeBuffer &cbuf) { + MacroAssembler _masm(&cbuf); + + address base = __ start_a_stub(size_exception_handler()); + if (base == NULL) return 0; // CodeBuffer::expand failed + + int offset = __ offset(); + __ b64_patchable((address)OptoRuntime::exception_blob()->content_begin(), + relocInfo::runtime_call_type); + assert(__ offset() - offset == (int)size_exception_handler(), "must be fixed size"); + __ end_a_stub(); + + return offset; +} + +// The deopt_handler is like the exception handler, but it calls to +// the deoptimization blob instead of jumping to the exception blob. +int emit_deopt_handler(CodeBuffer& cbuf) { + MacroAssembler _masm(&cbuf); + + address base = __ start_a_stub(size_deopt_handler()); + if (base == NULL) return 0; // CodeBuffer::expand failed + + int offset = __ offset(); + __ bl64_patchable((address)SharedRuntime::deopt_blob()->unpack(), + relocInfo::runtime_call_type); + assert(__ offset() - offset == (int) size_deopt_handler(), "must be fixed size"); + __ end_a_stub(); + + return offset; +} + +//============================================================================= + +// Use a frame slots bias for frameless methods if accessing the stack. +static int frame_slots_bias(int reg_enc, PhaseRegAlloc* ra_) { + if (as_Register(reg_enc) == R1_SP) { + return 0; // TODO: PPC port ra_->C->frame_slots_sp_bias_in_bytes(); + } + return 0; +} + +const bool Matcher::match_rule_supported(int opcode) { + if (!has_match_rule(opcode)) + return false; + + switch (opcode) { + case Op_CountLeadingZerosI: + case Op_CountLeadingZerosL: + case Op_CountTrailingZerosI: + case Op_CountTrailingZerosL: + if (!UseCountLeadingZerosInstructionsPPC64) + return false; + break; + + case Op_PopCountI: + case Op_PopCountL: + return (UsePopCountInstruction && VM_Version::has_popcntw()); + + case Op_StrComp: + return SpecialStringCompareTo; + case Op_StrEquals: + return SpecialStringEquals; + case Op_StrIndexOf: + return SpecialStringIndexOf; + } + + return true; // Per default match rules are supported. +} + +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. + return VM_Version::has_fcfids(); // False means that conversion is done by runtime call. +} + +// Vector width in bytes. +const int Matcher::vector_width_in_bytes(BasicType bt) { + assert(MaxVectorSize == 8, ""); + return 8; +} + +// Vector ideal reg. +const int Matcher::vector_ideal_reg(int size) { + assert(MaxVectorSize == 8 && size == 8, ""); + return Op_RegL; +} + +const int Matcher::vector_shift_count_ideal_reg(int size) { + fatal("vector shift is not supported"); + return Node::NotAMachineReg; +} + +// Limits on vector size (number of elements) loaded into vector. +const int Matcher::max_vector_size(const BasicType bt) { + assert(is_java_primitive(bt), "only primitive type vectors"); + return vector_width_in_bytes(bt)/type2aelembytes(bt); +} + +const int Matcher::min_vector_size(const BasicType bt) { + return max_vector_size(bt); // Same as max. +} + +// PPC doesn't support misaligned vectors store/load. +const bool Matcher::misaligned_vectors_ok() { + return false; +} + +// RETURNS: whether this branch offset is short enough that a short +// branch can be used. +// +// If the platform does not provide any short branch variants, then +// this method should return `false' for offset 0. +// +// `Compile::Fill_buffer' will decide on basis of this information +// whether to do the pass `Compile::Shorten_branches' at all. +// +// And `Compile::Shorten_branches' will decide on basis of this +// information whether to replace particular branch sites by short +// ones. +bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { + // Is the offset within the range of a ppc64 pc relative branch? + bool b; + + const int safety_zone = 3 * BytesPerInstWord; + b = Assembler::is_simm((offset<0 ? offset-safety_zone : offset+safety_zone), + 29 - 16 + 1 + 2); + return b; +} + +const bool Matcher::isSimpleConstant64(jlong value) { + // Probably always true, even if a temp register is required. + return true; +} +/* TODO: PPC port +// Make a new machine dependent decode node (with its operands). +MachTypeNode *Matcher::make_decode_node(Compile *C) { + assert(Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0, + "This method is only implemented for unscaled cOops mode so far"); + MachTypeNode *decode = new (C) decodeN_unscaledNode(); + decode->set_opnd_array(0, new (C) iRegPdstOper()); + decode->set_opnd_array(1, new (C) iRegNsrcOper()); + return decode; +} +*/ +// Threshold size for cleararray. +const int Matcher::init_array_short_size = 8 * BytesPerLong; + +// false => size gets scaled to BytesPerLong, ok. +const bool Matcher::init_array_count_is_in_bytes = false; + +// Use conditional move (CMOVL) on Power7. +const int Matcher::long_cmove_cost() { return 0; } // this only makes long cmoves more expensive than int cmoves + +// Suppress CMOVF. Conditional move available (sort of) on PPC64 only from P7 onwards. Not exploited yet. +// fsel doesn't accept a condition register as input, so this would be slightly different. +const int Matcher::float_cmove_cost() { return ConditionalMoveLimit; } + +// Power6 requires postalloc expand (see block.cpp for description of postalloc expand). +const bool Matcher::require_postalloc_expand = true; + +// Should the Matcher clone shifts on addressing modes, expecting them to +// be subsumed into complex addressing expressions or compute them into +// registers? True for Intel but false for most RISCs. +const bool Matcher::clone_shift_expressions = false; + +// Do we need to mask the count passed to shift instructions or does +// the cpu only look at the lower 5/6 bits anyway? +// Off, as masks are generated in expand rules where required. +// Constant shift counts are handled in Ideal phase. +const bool Matcher::need_masked_shift_count = false; + +// This affects two different things: +// - how Decode nodes are matched +// - how ImplicitNullCheck opportunities are recognized +// If true, the matcher will try to remove all Decodes and match them +// (as operands) into nodes. NullChecks are not prepared to deal with +// Decodes by final_graph_reshaping(). +// If false, final_graph_reshaping() forces the decode behind the Cmp +// for a NullCheck. The matcher matches the Decode node into a register. +// Implicit_null_check optimization moves the Decode along with the +// memory operation back up before the NullCheck. +bool Matcher::narrow_oop_use_complex_address() { + // TODO: PPC port if (MatchDecodeNodes) return true; + return false; +} + +bool Matcher::narrow_klass_use_complex_address() { + NOT_LP64(ShouldNotCallThis()); + assert(UseCompressedClassPointers, "only for compressed klass code"); + // TODO: PPC port if (MatchDecodeNodes) return true; + return false; +} + +// Is it better to copy float constants, or load them directly from memory? +// Intel can load a float constant from a direct address, requiring no +// extra registers. Most RISCs will have to materialize an address into a +// register first, so they would do better to copy the constant from stack. +const bool Matcher::rematerialize_float_constants = false; + +// If CPU can load and store mis-aligned doubles directly then no fixup is +// needed. Else we split the double into 2 integer pieces and move it +// piece-by-piece. Only happens when passing doubles into C code as the +// Java calling convention forces doubles to be aligned. +const bool Matcher::misaligned_doubles_ok = true; + +void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { + Unimplemented(); +} + +// Advertise here if the CPU requires explicit rounding operations +// to implement the UseStrictFP mode. +const bool Matcher::strict_fp_requires_explicit_rounding = false; + +// Do floats take an entire double register or just half? +// +// A float occupies a ppc64 double register. For the allocator, a +// ppc64 double register appears as a pair of float registers. +bool Matcher::float_in_double() { return true; } + +// Do ints take an entire long register or just half? +// The relevant question is how the int is callee-saved: +// the whole long is written but de-opt'ing will have to extract +// the relevant 32 bits. +const bool Matcher::int_in_long = true; + +// Constants for c2c and c calling conventions. + +const MachRegisterNumbers iarg_reg[8] = { + R3_num, R4_num, R5_num, R6_num, + R7_num, R8_num, R9_num, R10_num +}; + +const MachRegisterNumbers farg_reg[13] = { + F1_num, F2_num, F3_num, F4_num, + F5_num, F6_num, F7_num, F8_num, + F9_num, F10_num, F11_num, F12_num, + F13_num +}; + +const int num_iarg_registers = sizeof(iarg_reg) / sizeof(iarg_reg[0]); + +const int num_farg_registers = sizeof(farg_reg) / sizeof(farg_reg[0]); + +// Return whether or not this register is ever used as an argument. This +// function is used on startup to build the trampoline stubs in generateOptoStub. +// Registers not mentioned will be killed by the VM call in the trampoline, and +// arguments in those registers not be available to the callee. +bool Matcher::can_be_java_arg(int reg) { + // We return true for all registers contained in iarg_reg[] and + // farg_reg[] and their virtual halves. + // We must include the virtual halves in order to get STDs and LDs + // instead of STWs and LWs in the trampoline stubs. + + if ( reg == R3_num || reg == R3_H_num + || reg == R4_num || reg == R4_H_num + || reg == R5_num || reg == R5_H_num + || reg == R6_num || reg == R6_H_num + || reg == R7_num || reg == R7_H_num + || reg == R8_num || reg == R8_H_num + || reg == R9_num || reg == R9_H_num + || reg == R10_num || reg == R10_H_num) + return true; + + if ( reg == F1_num || reg == F1_H_num + || reg == F2_num || reg == F2_H_num + || reg == F3_num || reg == F3_H_num + || reg == F4_num || reg == F4_H_num + || reg == F5_num || reg == F5_H_num + || reg == F6_num || reg == F6_H_num + || reg == F7_num || reg == F7_H_num + || reg == F8_num || reg == F8_H_num + || reg == F9_num || reg == F9_H_num + || reg == F10_num || reg == F10_H_num + || reg == F11_num || reg == F11_H_num + || reg == F12_num || reg == F12_H_num + || reg == F13_num || reg == F13_H_num) + return true; + + return false; +} + +bool Matcher::is_spillable_arg(int reg) { + return can_be_java_arg(reg); +} + +bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { + return false; +} + +// Register for DIVI projection of divmodI. +RegMask Matcher::divI_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for MODI projection of divmodI. +RegMask Matcher::modI_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for DIVL projection of divmodL. +RegMask Matcher::divL_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +// Register for MODL projection of divmodL. +RegMask Matcher::modL_proj_mask() { + ShouldNotReachHere(); + return RegMask(); +} + +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return RegMask(); +} + +const RegMask Matcher::mathExactI_result_proj_mask() { + return RARG4_BITS64_REG_mask(); +} + +const RegMask Matcher::mathExactL_result_proj_mask() { + return RARG4_BITS64_REG_mask(); +} + +const RegMask Matcher::mathExactI_flags_proj_mask() { + return INT_FLAGS_mask(); +} + +%} + +//----------ENCODING BLOCK----------------------------------------------------- +// This block specifies the encoding classes used by the compiler to output +// byte streams. Encoding classes are parameterized macros used by +// Machine Instruction Nodes in order to generate the bit encoding of the +// instruction. Operands specify their base encoding interface with the +// interface keyword. There are currently supported four interfaces, +// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an +// operand to generate a function which returns its register number when +// queried. CONST_INTER causes an operand to generate a function which +// returns the value of the constant when queried. MEMORY_INTER causes an +// operand to generate four functions which return the Base Register, the +// Index Register, the Scale Value, and the Offset Value of the operand when +// queried. COND_INTER causes an operand to generate six functions which +// return the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional instruction. +// +// Instructions specify two basic values for encoding. Again, a function +// is available to check if the constant displacement is an oop. They use the +// ins_encode keyword to specify their encoding classes (which must be +// a sequence of enc_class names, and their parameters, specified in +// the encoding block), and they use the +// opcode keyword to specify, in order, their primary, secondary, and +// tertiary opcode. Only the opcode sections which a particular instruction +// needs for encoding need to be specified. +encode %{ + enc_class enc_unimplemented %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + MacroAssembler _masm(&cbuf); + __ unimplemented("Unimplemented mach node encoding in AD file.", 13); + %} + + enc_class enc_untested %{ +#ifdef ASSERT + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + 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); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lbz($dst$$Register, Idisp, $mem$$base$$Register); + %} + + // Load acquire. + enc_class enc_lbz_ac(iRegIdst dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lbz($dst$$Register, Idisp, $mem$$base$$Register); + __ twi_0($dst$$Register); + __ isync(); + %} + + enc_class enc_lhz(iRegIdst dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lhz); + + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lhz($dst$$Register, Idisp, $mem$$base$$Register); + %} + + // Load acquire. + enc_class enc_lhz_ac(iRegIdst dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lhz($dst$$Register, Idisp, $mem$$base$$Register); + __ twi_0($dst$$Register); + __ isync(); + %} + + enc_class enc_lwz(iRegIdst dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lwz); + + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lwz($dst$$Register, Idisp, $mem$$base$$Register); + %} + + // Load acquire. + enc_class enc_lwz_ac(iRegIdst dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ lwz($dst$$Register, Idisp, $mem$$base$$Register); + __ twi_0($dst$$Register); + __ isync(); + %} + + enc_class enc_ld(iRegLdst dst, memoryAlg4 mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_ld); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + // Operand 'ds' requires 4-alignment. + assert((Idisp & 0x3) == 0, "unaligned offset"); + __ ld($dst$$Register, Idisp, $mem$$base$$Register); + %} + + // Load acquire. + enc_class enc_ld_ac(iRegLdst dst, memoryAlg4 mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + // Operand 'ds' requires 4-alignment. + assert((Idisp & 0x3) == 0, "unaligned offset"); + __ ld($dst$$Register, Idisp, $mem$$base$$Register); + __ twi_0($dst$$Register); + __ isync(); + %} + + enc_class enc_lfd(RegF dst, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lfd); + 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); + + MacroAssembler _masm(&cbuf); + int toc_offset = 0; + + if (!ra_->C->in_scratch_emit_size()) { + address const_toc_addr; + // Create a non-oop constant, no relocation needed. + // If it is an IC, it has a virtual_call_Relocation. + const_toc_addr = __ long_constant((jlong)$src$$constant); + + // Get the constant's TOC offset. + toc_offset = __ offset_to_method_toc(const_toc_addr); + + // Keep the current instruction offset in mind. + ((loadConLNode*)this)->_cbuf_insts_offset = __ offset(); + } + + __ ld($dst$$Register, toc_offset, $toc$$Register); + %} + + enc_class enc_load_long_constL_hi(iRegLdst dst, iRegLdst toc, immL src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addis); + + MacroAssembler _masm(&cbuf); + + if (!ra_->C->in_scratch_emit_size()) { + address const_toc_addr; + // Create a non-oop constant, no relocation needed. + // If it is an IC, it has a virtual_call_Relocation. + const_toc_addr = __ long_constant((jlong)$src$$constant); + + // Get the constant's TOC offset. + const int toc_offset = __ offset_to_method_toc(const_toc_addr); + // Store the toc offset of the constant. + ((loadConL_hiNode*)this)->_const_toc_offset = toc_offset; + + // Also keep the current instruction offset in mind. + ((loadConL_hiNode*)this)->_cbuf_insts_offset = __ offset(); + } + + __ addis($dst$$Register, $toc$$Register, MacroAssembler::largeoffset_si16_si16_hi(_const_toc_offset)); + %} + +%} // encode + +source %{ + +typedef struct { + loadConL_hiNode *_large_hi; + loadConL_loNode *_large_lo; + loadConLNode *_small; + MachNode *_last; +} loadConLNodesTuple; + +loadConLNodesTuple loadConLNodesTuple_create(Compile *C, PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc, + OptoReg::Name reg_second, OptoReg::Name reg_first) { + loadConLNodesTuple nodes; + + const bool large_constant_pool = true; // TODO: PPC port C->cfg()->_consts_size > 4000; + if (large_constant_pool) { + // Create new nodes. + loadConL_hiNode *m1 = new (C) loadConL_hiNode(); + loadConL_loNode *m2 = new (C) loadConL_loNode(); + + // inputs for new nodes + m1->add_req(NULL, toc); + m2->add_req(NULL, m1); + + // operands for new nodes + m1->_opnds[0] = new (C) iRegLdstOper(); // dst + m1->_opnds[1] = immSrc; // src + m1->_opnds[2] = new (C) iRegPdstOper(); // toc + m2->_opnds[0] = new (C) iRegLdstOper(); // dst + m2->_opnds[1] = immSrc; // src + m2->_opnds[2] = new (C) iRegLdstOper(); // base + + // Initialize ins_attrib TOC fields. + m1->_const_toc_offset = -1; + m2->_const_toc_offset_hi_node = m1; + + // Initialize ins_attrib instruction offset. + m1->_cbuf_insts_offset = -1; + + // register allocation for new nodes + ra_->set_pair(m1->_idx, reg_second, reg_first); + ra_->set_pair(m2->_idx, reg_second, reg_first); + + // Create result. + nodes._large_hi = m1; + nodes._large_lo = m2; + nodes._small = NULL; + nodes._last = nodes._large_lo; + assert(m2->bottom_type()->isa_long(), "must be long"); + } else { + loadConLNode *m2 = new (C) loadConLNode(); + + // inputs for new nodes + m2->add_req(NULL, toc); + + // operands for new nodes + m2->_opnds[0] = new (C) iRegLdstOper(); // dst + m2->_opnds[1] = immSrc; // src + m2->_opnds[2] = new (C) iRegPdstOper(); // toc + + // Initialize ins_attrib instruction offset. + m2->_cbuf_insts_offset = -1; + + // register allocation for new nodes + ra_->set_pair(m2->_idx, reg_second, reg_first); + + // Create result. + nodes._large_hi = NULL; + nodes._large_lo = NULL; + nodes._small = m2; + nodes._last = nodes._small; + assert(m2->bottom_type()->isa_long(), "must be long"); + } + + return nodes; +} + +%} // source + +encode %{ + // Postalloc expand emitter for loading a long constant from the method's TOC. + // Enc_class needed as consttanttablebase is not supported by postalloc + // expand. + enc_class postalloc_expand_load_long_constant(iRegLdst dst, immL src, iRegLdst toc) %{ + // Create new nodes. + loadConLNodesTuple loadConLNodes = + loadConLNodesTuple_create(C, ra_, n_toc, op_src, + ra_->get_reg_second(this), ra_->get_reg_first(this)); + + // Push new nodes. + if (loadConLNodes._large_hi) nodes->push(loadConLNodes._large_hi); + if (loadConLNodes._last) nodes->push(loadConLNodes._last); + + // some asserts + assert(nodes->length() >= 1, "must have created at least 1 node"); + assert(loadConLNodes._last->bottom_type()->isa_long(), "must be long"); + %} + + enc_class enc_load_long_constP(iRegLdst dst, immP src, iRegLdst toc) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_ld); + + MacroAssembler _masm(&cbuf); + int toc_offset = 0; + + if (!ra_->C->in_scratch_emit_size()) { + intptr_t val = $src$$constant; + relocInfo::relocType constant_reloc = $src->constant_reloc(); // src + address const_toc_addr; + if (constant_reloc == relocInfo::oop_type) { + // Create an oop constant and a corresponding relocation. + AddressLiteral a = __ allocate_oop_address((jobject)val); + const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); + __ relocate(a.rspec()); + } else if (constant_reloc == relocInfo::metadata_type) { + AddressLiteral a = __ allocate_metadata_address((Metadata *)val); + const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); + __ relocate(a.rspec()); + } else { + // Create a non-oop constant, no relocation needed. + const_toc_addr = __ long_constant((jlong)$src$$constant); + } + + // Get the constant's TOC offset. + toc_offset = __ offset_to_method_toc(const_toc_addr); + } + + __ ld($dst$$Register, toc_offset, $toc$$Register); + %} + + enc_class enc_load_long_constP_hi(iRegLdst dst, immP src, iRegLdst toc) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addis); + + MacroAssembler _masm(&cbuf); + if (!ra_->C->in_scratch_emit_size()) { + intptr_t val = $src$$constant; + relocInfo::relocType constant_reloc = $src->constant_reloc(); // src + address const_toc_addr; + if (constant_reloc == relocInfo::oop_type) { + // Create an oop constant and a corresponding relocation. + AddressLiteral a = __ allocate_oop_address((jobject)val); + const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); + __ relocate(a.rspec()); + } else if (constant_reloc == relocInfo::metadata_type) { + AddressLiteral a = __ allocate_metadata_address((Metadata *)val); + const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); + __ relocate(a.rspec()); + } else { // non-oop pointers, e.g. card mark base, heap top + // Create a non-oop constant, no relocation needed. + const_toc_addr = __ long_constant((jlong)$src$$constant); + } + + // Get the constant's TOC offset. + const int toc_offset = __ offset_to_method_toc(const_toc_addr); + // Store the toc offset of the constant. + ((loadConP_hiNode*)this)->_const_toc_offset = toc_offset; + } + + __ addis($dst$$Register, $toc$$Register, MacroAssembler::largeoffset_si16_si16_hi(_const_toc_offset)); + %} + + // Postalloc expand emitter for loading a ptr constant from the method's TOC. + // Enc_class needed as consttanttablebase is not supported by postalloc + // expand. + enc_class postalloc_expand_load_ptr_constant(iRegPdst dst, immP src, iRegLdst toc) %{ + const bool large_constant_pool = true; // TODO: PPC port C->cfg()->_consts_size > 4000; + if (large_constant_pool) { + // Create new nodes. + loadConP_hiNode *m1 = new (C) loadConP_hiNode(); + loadConP_loNode *m2 = new (C) loadConP_loNode(); + + // inputs for new nodes + m1->add_req(NULL, n_toc); + m2->add_req(NULL, m1); + + // operands for new nodes + m1->_opnds[0] = new (C) iRegPdstOper(); // dst + m1->_opnds[1] = op_src; // src + m1->_opnds[2] = new (C) iRegPdstOper(); // toc + m2->_opnds[0] = new (C) iRegPdstOper(); // dst + m2->_opnds[1] = op_src; // src + m2->_opnds[2] = new (C) iRegLdstOper(); // base + + // Initialize ins_attrib TOC fields. + m1->_const_toc_offset = -1; + m2->_const_toc_offset_hi_node = m1; + + // Register allocation for new nodes. + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(m1); + nodes->push(m2); + assert(m2->bottom_type()->isa_ptr(), "must be ptr"); + } else { + loadConPNode *m2 = new (C) loadConPNode(); + + // inputs for new nodes + m2->add_req(NULL, n_toc); + + // operands for new nodes + m2->_opnds[0] = new (C) iRegPdstOper(); // dst + m2->_opnds[1] = op_src; // src + m2->_opnds[2] = new (C) iRegPdstOper(); // toc + + // Register allocation for new nodes. + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(m2); + assert(m2->bottom_type()->isa_ptr(), "must be ptr"); + } + %} + + // Enc_class needed as consttanttablebase is not supported by postalloc + // expand. + enc_class postalloc_expand_load_float_constant(regF dst, immF src, iRegLdst toc) %{ + bool large_constant_pool = true; // TODO: PPC port C->cfg()->_consts_size > 4000; + + MachNode *m2; + if (large_constant_pool) { + m2 = new (C) loadConFCompNode(); + } else { + m2 = new (C) loadConFNode(); + } + // inputs for new nodes + m2->add_req(NULL, n_toc); + + // operands for new nodes + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_src; + m2->_opnds[2] = new (C) iRegPdstOper(); // constanttablebase + + // register allocation for new nodes + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m2); + %} + + // Enc_class needed as consttanttablebase is not supported by postalloc + // expand. + enc_class postalloc_expand_load_double_constant(regD dst, immD src, iRegLdst toc) %{ + bool large_constant_pool = true; // TODO: PPC port C->cfg()->_consts_size > 4000; + + MachNode *m2; + if (large_constant_pool) { + m2 = new (C) loadConDCompNode(); + } else { + m2 = new (C) loadConDNode(); + } + // inputs for new nodes + m2->add_req(NULL, n_toc); + + // operands for new nodes + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_src; + m2->_opnds[2] = new (C) iRegPdstOper(); // constanttablebase + + // register allocation for new nodes + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m2); + %} + + enc_class enc_stw(iRegIsrc src, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_stw); + 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); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + // Operand 'ds' requires 4-alignment. + assert((Idisp & 0x3) == 0, "unaligned offset"); + __ std($src$$Register, Idisp, $mem$$base$$Register); + %} + + enc_class enc_stfs(RegF src, memory mem) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_stfs); + 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); + MacroAssembler _masm(&cbuf); + int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_); + __ stfd($src$$FloatRegister, Idisp, $mem$$base$$Register); + %} + + // 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) %{ + // 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. + // + // Proposed code sequence for the cmove implementation: + // + // Label skip_release; + // __ beq(CCRfixed, skip_release); + // __ release(); + // __ bind(skip_release); + // __ stb(card mark); + + MacroAssembler _masm(&cbuf); + Label skip_storestore; + +#if 0 // TODO: PPC port + // Check CMSCollectorCardTableModRefBSExt::_requires_release and do the + // StoreStore barrier conditionally. + __ lwz(R0, 0, $releaseFieldAddr$$Register); + __ cmpwi(CCR0, R0, 0); + __ beq_predict_taken(CCR0, skip_release); +#endif + __ li(R0, 0); + __ membar(Assembler::StoreStore); +#if 0 // TODO: PPC port + __ bind(skip_storestore); +#endif + + // Do the store. + if ($mem$$index == 0) { + __ stb(R0, $mem$$disp, $mem$$base$$Register); + } else { + assert(0 == $mem$$disp, "no displacement possible with indexed load/stores on ppc"); + __ stbx(R0, $mem$$base$$Register, $mem$$index$$Register); + } + %} + + enc_class postalloc_expand_encode_oop(iRegNdst dst, iRegPdst src, flagsReg crx) %{ + + if (VM_Version::has_isel()) { + // use isel instruction with Power 7 + cmpP_reg_imm16Node *n_compare = new (C) cmpP_reg_imm16Node(); + encodeP_subNode *n_sub_base = new (C) encodeP_subNode(); + encodeP_shiftNode *n_shift = new (C) encodeP_shiftNode(); + cond_set_0_oopNode *n_cond_set = new (C) cond_set_0_oopNode(); + + n_compare->add_req(n_region, n_src); + n_compare->_opnds[0] = op_crx; + n_compare->_opnds[1] = op_src; + n_compare->_opnds[2] = new (C) immL16Oper(0); + + n_sub_base->add_req(n_region, n_src); + n_sub_base->_opnds[0] = op_dst; + n_sub_base->_opnds[1] = op_src; + n_sub_base->_bottom_type = _bottom_type; + + n_shift->add_req(n_region, n_sub_base); + n_shift->_opnds[0] = op_dst; + n_shift->_opnds[1] = op_dst; + n_shift->_bottom_type = _bottom_type; + + n_cond_set->add_req(n_region, n_compare, n_shift); + n_cond_set->_opnds[0] = op_dst; + n_cond_set->_opnds[1] = op_crx; + n_cond_set->_opnds[2] = op_dst; + n_cond_set->_bottom_type = _bottom_type; + + ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx)); + ra_->set_pair(n_sub_base->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_shift->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n_compare); + nodes->push(n_sub_base); + nodes->push(n_shift); + nodes->push(n_cond_set); + + } else { + // before Power 7 + moveRegNode *n_move = new (C) moveRegNode(); + cmpP_reg_imm16Node *n_compare = new (C) cmpP_reg_imm16Node(); + encodeP_shiftNode *n_shift = new (C) encodeP_shiftNode(); + cond_sub_baseNode *n_sub_base = new (C) cond_sub_baseNode(); + + n_move->add_req(n_region, n_src); + n_move->_opnds[0] = op_dst; + n_move->_opnds[1] = op_src; + ra_->set_oop(n_move, true); // Until here, 'n_move' still produces an oop. + + n_compare->add_req(n_region, n_src); + n_compare->add_prec(n_move); + + n_compare->_opnds[0] = op_crx; + n_compare->_opnds[1] = op_src; + n_compare->_opnds[2] = new (C) immL16Oper(0); + + n_sub_base->add_req(n_region, n_compare, n_src); + n_sub_base->_opnds[0] = op_dst; + n_sub_base->_opnds[1] = op_crx; + n_sub_base->_opnds[2] = op_src; + n_sub_base->_bottom_type = _bottom_type; + + n_shift->add_req(n_region, n_sub_base); + n_shift->_opnds[0] = op_dst; + n_shift->_opnds[1] = op_dst; + n_shift->_bottom_type = _bottom_type; + + ra_->set_pair(n_shift->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx)); + ra_->set_pair(n_sub_base->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_move->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n_move); + nodes->push(n_compare); + nodes->push(n_sub_base); + nodes->push(n_shift); + } + + assert(!(ra_->is_oop(this)), "sanity"); // This is not supposed to be GC'ed. + %} + + enc_class postalloc_expand_encode_oop_not_null(iRegNdst dst, iRegPdst src) %{ + + encodeP_subNode *n1 = new (C) encodeP_subNode(); + n1->add_req(n_region, n_src); + n1->_opnds[0] = op_dst; + n1->_opnds[1] = op_src; + n1->_bottom_type = _bottom_type; + + encodeP_shiftNode *n2 = new (C) encodeP_shiftNode(); + n2->add_req(n_region, n1); + n2->_opnds[0] = op_dst; + n2->_opnds[1] = op_dst; + n2->_bottom_type = _bottom_type; + ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n1); + nodes->push(n2); + assert(!(ra_->is_oop(this)), "sanity"); // This is not supposed to be GC'ed. + %} + + enc_class postalloc_expand_decode_oop(iRegPdst dst, iRegNsrc src, flagsReg crx) %{ + decodeN_shiftNode *n_shift = new (C) decodeN_shiftNode(); + cmpN_reg_imm0Node *n_compare = new (C) cmpN_reg_imm0Node(); + + n_compare->add_req(n_region, n_src); + n_compare->_opnds[0] = op_crx; + n_compare->_opnds[1] = op_src; + n_compare->_opnds[2] = new (C) immN_0Oper(TypeNarrowOop::NULL_PTR); + + n_shift->add_req(n_region, n_src); + n_shift->_opnds[0] = op_dst; + n_shift->_opnds[1] = op_src; + n_shift->_bottom_type = _bottom_type; + + if (VM_Version::has_isel()) { + // use isel instruction with Power 7 + + decodeN_addNode *n_add_base = new (C) decodeN_addNode(); + n_add_base->add_req(n_region, n_shift); + n_add_base->_opnds[0] = op_dst; + n_add_base->_opnds[1] = op_dst; + n_add_base->_bottom_type = _bottom_type; + + cond_set_0_ptrNode *n_cond_set = new (C) cond_set_0_ptrNode(); + n_cond_set->add_req(n_region, n_compare, n_add_base); + n_cond_set->_opnds[0] = op_dst; + n_cond_set->_opnds[1] = op_crx; + n_cond_set->_opnds[2] = op_dst; + n_cond_set->_bottom_type = _bottom_type; + + assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!"); + ra_->set_oop(n_cond_set, true); + + ra_->set_pair(n_shift->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx)); + ra_->set_pair(n_add_base->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n_compare); + nodes->push(n_shift); + nodes->push(n_add_base); + nodes->push(n_cond_set); + + } else { + // before Power 7 + cond_add_baseNode *n_add_base = new (C) cond_add_baseNode(); + + n_add_base->add_req(n_region, n_compare, n_shift); + n_add_base->_opnds[0] = op_dst; + n_add_base->_opnds[1] = op_crx; + n_add_base->_opnds[2] = op_dst; + n_add_base->_bottom_type = _bottom_type; + + assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!"); + ra_->set_oop(n_add_base, true); + + ra_->set_pair(n_shift->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx)); + ra_->set_pair(n_add_base->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n_compare); + nodes->push(n_shift); + nodes->push(n_add_base); + } + %} + + enc_class postalloc_expand_decode_oop_not_null(iRegPdst dst, iRegNsrc src) %{ + decodeN_shiftNode *n1 = new (C) decodeN_shiftNode(); + n1->add_req(n_region, n_src); + n1->_opnds[0] = op_dst; + n1->_opnds[1] = op_src; + n1->_bottom_type = _bottom_type; + + decodeN_addNode *n2 = new (C) decodeN_addNode(); + n2->add_req(n_region, n1); + n2->_opnds[0] = op_dst; + n2->_opnds[1] = op_dst; + n2->_bottom_type = _bottom_type; + ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!"); + ra_->set_oop(n2, true); + + nodes->push(n1); + nodes->push(n2); + %} + + enc_class enc_cmove_reg(iRegIdst dst, flagsReg crx, iRegIsrc src, cmpOp cmp) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + + MacroAssembler _masm(&cbuf); + int cc = $cmp$$cmpcode; + int flags_reg = $crx$$reg; + Label done; + assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding"); + // 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, flagsReg crx, immI16 src, cmpOp cmp) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + + MacroAssembler _masm(&cbuf); + 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); + __ li($dst$$Register, $src$$constant); + // TODO PPC port __ endgroup_if_needed(_size == 12); + __ bind(done); + %} + + // New atomics. + enc_class enc_GetAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + Register Rtmp = R0; + Register Rres = $res$$Register; + Register Rsrc = $src$$Register; + Register Rptr = $mem_ptr$$Register; + bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); + Register Rold = RegCollision ? Rtmp : Rres; + + Label Lretry; + __ bind(Lretry); + __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); + __ add(Rtmp, Rsrc, Rold); + __ stwcx_(Rtmp, Rptr); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + __ bne_predict_not_taken(CCR0, Lretry); + } else { + __ bne( CCR0, Lretry); + } + if (RegCollision) __ subf(Rres, Rsrc, Rtmp); + __ fence(); + %} + + enc_class enc_GetAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + Register Rtmp = R0; + Register Rres = $res$$Register; + Register Rsrc = $src$$Register; + Register Rptr = $mem_ptr$$Register; + bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); + Register Rold = RegCollision ? Rtmp : Rres; + + Label Lretry; + __ bind(Lretry); + __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); + __ add(Rtmp, Rsrc, Rold); + __ stdcx_(Rtmp, Rptr); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + __ bne_predict_not_taken(CCR0, Lretry); + } else { + __ bne( CCR0, Lretry); + } + if (RegCollision) __ subf(Rres, Rsrc, Rtmp); + __ fence(); + %} + + enc_class enc_GetAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + Register Rtmp = R0; + Register Rres = $res$$Register; + Register Rsrc = $src$$Register; + Register Rptr = $mem_ptr$$Register; + bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); + Register Rold = RegCollision ? Rtmp : Rres; + + Label Lretry; + __ bind(Lretry); + __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); + __ stwcx_(Rsrc, Rptr); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + __ bne_predict_not_taken(CCR0, Lretry); + } else { + __ bne( CCR0, Lretry); + } + if (RegCollision) __ mr(Rres, Rtmp); + __ fence(); + %} + + enc_class enc_GetAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + Register Rtmp = R0; + Register Rres = $res$$Register; + Register Rsrc = $src$$Register; + Register Rptr = $mem_ptr$$Register; + bool RegCollision = (Rres == Rsrc) || (Rres == Rptr); + Register Rold = RegCollision ? Rtmp : Rres; + + Label Lretry; + __ bind(Lretry); + __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update()); + __ stdcx_(Rsrc, Rptr); + if (UseStaticBranchPredictionInCompareAndSwapPPC64) { + __ bne_predict_not_taken(CCR0, Lretry); + } else { + __ bne( CCR0, Lretry); + } + if (RegCollision) __ mr(Rres, Rtmp); + __ fence(); + %} + + // 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); + 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); + + MacroAssembler _masm(&cbuf); + + Label done; + __ cmpwi($crx$$CondRegister, $src$$Register, 0); + __ li($dst$$Register, $zero$$constant); + __ beq($crx$$CondRegister, done); + __ li($dst$$Register, $notzero$$constant); + __ bind(done); + %} + + enc_class enc_convP2B_regP__cmove(iRegIdst dst, iRegPsrc src, flagsReg crx, immI16 zero, immI16 notzero) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + + Label done; + __ cmpdi($crx$$CondRegister, $src$$Register, 0); + __ li($dst$$Register, $zero$$constant); + __ beq($crx$$CondRegister, done); + __ li($dst$$Register, $notzero$$constant); + __ bind(done); + %} + + enc_class enc_cmove_bso_stackSlotL(iRegLdst dst, flagsReg crx, stackSlotL mem ) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + + 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_bc(flagsReg crx, cmpOp cmp, Label lbl) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_bc); + + 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; + assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding"); + int bhint = Assembler::bhintNoHint; + + if (UseStaticBranchPredictionForUncommonPathsPPC64) { + if (_prob <= PROB_NEVER) { + bhint = Assembler::bhintIsNotTaken; + } else if (_prob >= PROB_ALWAYS) { + bhint = Assembler::bhintIsTaken; + } + } + + __ bc(Assembler::add_bhint_to_boint(bhint, cc_to_boint(cc)), + cc_to_biint(cc, flags_reg), + l); + %} + + enc_class enc_bc_far(flagsReg 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); + + 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; + } + } + + // 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); + %} + + // Branch used with Power6 scheduling (can be shortened without changing the node). + enc_class enc_bc_short_far(flagsReg 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); + + 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 + // expand. + enc_class postalloc_expand_load_replF_constant(iRegLdst dst, immF src, iRegLdst toc) %{ + // Create new nodes. + + // Make an operand with the bit pattern to load as float. + immLOper *op_repl = new (C) immLOper((jlong)replicate_immF(op_src->constantF())); + + loadConLNodesTuple loadConLNodes = + loadConLNodesTuple_create(C, ra_, n_toc, op_repl, + ra_->get_reg_second(this), ra_->get_reg_first(this)); + + // Push new nodes. + if (loadConLNodes._large_hi) nodes->push(loadConLNodes._large_hi); + if (loadConLNodes._last) nodes->push(loadConLNodes._last); + + assert(nodes->length() >= 1, "must have created at least 1 node"); + assert(loadConLNodes._last->bottom_type()->isa_long(), "must be long"); + %} + + // 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"); + + MacroAssembler _masm(&cbuf); + // Mark the code position where the load from the safepoint + // polling page was emitted as relocInfo::poll_type. + __ relocate(relocInfo::poll_type); + __ load_from_polling_page($poll$$Register); + %} + + // A Java static call or a runtime call. + // + // Branch-and-link relative to a trampoline. + // The trampoline loads the target address and does a long branch to there. + // In case we call java, the trampoline branches to a interpreter_stub + // which loads the inline cache and the real call target from the constant pool. + // + // This basically looks like this: + // + // >>>> consts -+ -+ + // | |- offset1 + // [call target1] | <-+ + // [IC cache] |- offset2 + // [call target2] <--+ + // + // <<<< consts + // >>>> insts + // + // bl offset16 -+ -+ ??? // How many bits available? + // | | + // <<<< insts | | + // >>>> stubs | | + // | |- trampoline_stub_Reloc + // trampoline stub: | <-+ + // r2 = toc | + // r2 = [r2 + offset1] | // Load call target1 from const section + // mtctr r2 | + // bctr |- static_stub_Reloc + // comp_to_interp_stub: <---+ + // r1 = toc + // ICreg = [r1 + IC_offset] // Load IC from const section + // r1 = [r1 + offset2] // Load call target2 from const section + // mtctr r1 + // bctr + // + // <<<< stubs + // + // The call instruction in the code either + // - Branches directly to a compiled method if the offset is encodable in instruction. + // - Branches to the trampoline stub if the offset to the compiled method is not encodable. + // - Branches to the compiled_to_interp stub if the target is interpreted. + // + // Further there are three relocations from the loads to the constants in + // the constant section. + // + // 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); + + MacroAssembler _masm(&cbuf); + address entry_point = (address)$meth$$method; + + if (!_method) { + // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap. + emit_call_with_trampoline_stub(_masm, entry_point, relocInfo::runtime_call_type); + } else { + // Remember the offset not the address. + const int start_offset = __ offset(); + // The trampoline stub. + if (!Compile::current()->in_scratch_emit_size()) { + // No entry point given, use the current pc. + // Make sure branch fits into + if (entry_point == 0) entry_point = __ pc(); + + // Put the entry point as a constant into the constant pool. + const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none); + const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); + + // Emit the trampoline stub which will be related to the branch-and-link below. + emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + __ relocate(_optimized_virtual ? + relocInfo::opt_virtual_call_type : relocInfo::static_call_type); + } + + // The real call. + // Note: At this point we do not have the address of the trampoline + // stub, and the entry point might be too far away for bl, so __ pc() + // serves as dummy and the bl will be patched later. + cbuf.set_insts_mark(); + __ bl(__ pc()); // Emits a relocation. + + // The stub for call to interpreter. + CompiledStaticCall::emit_to_interp_stub(cbuf); + } + %} + + // Emit a method handle call. + // + // Method handle calls from compiled to compiled are going thru a + // c2i -> i2c adapter, extending the frame for their arguments. The + // caller however, returns directly to the compiled callee, that has + // to cope with the extended frame. We restore the original frame by + // loading the callers sp and adding the calculated framesize. + enc_class enc_java_handle_call(method meth) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + address entry_point = (address)$meth$$method; + + // Remember the offset not the address. + const int start_offset = __ offset(); + // The trampoline stub. + if (!ra_->C->in_scratch_emit_size()) { + // No entry point given, use the current pc. + // Make sure branch fits into + if (entry_point == 0) entry_point = __ pc(); + + // Put the entry point as a constant into the constant pool. + const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none); + const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); + + // Emit the trampoline stub which will be related to the branch-and-link below. + emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + assert(_optimized_virtual, "methodHandle call should be a virtual call"); + __ relocate(relocInfo::opt_virtual_call_type); + } + + // The real call. + // Note: At this point we do not have the address of the trampoline + // stub, and the entry point might be too far away for bl, so __ pc() + // serves as dummy and the bl will be patched later. + cbuf.set_insts_mark(); + __ bl(__ pc()); // Emits a relocation. + + assert(_method, "execute next statement conditionally"); + // The stub for call to interpreter. + CompiledStaticCall::emit_to_interp_stub(cbuf); + + // Restore original sp. + __ ld(R11_scratch1, 0, R1_SP); // Load caller sp. + const long framesize = ra_->C->frame_slots() << LogBytesPerInt; + unsigned int bytes = (unsigned int)framesize; + long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes); + if (Assembler::is_simm(-offset, 16)) { + __ addi(R1_SP, R11_scratch1, -offset); + } else { + __ load_const_optimized(R12_scratch2, -offset); + __ add(R1_SP, R11_scratch1, R12_scratch2); + } +#ifdef ASSERT + __ ld(R12_scratch2, 0, R1_SP); // Load from unextended_sp. + __ cmpd(CCR0, R11_scratch1, R12_scratch2); + __ asm_assert_eq("backlink changed", 0x8000); +#endif + // If fails should store backlink before unextending. + + if (ra_->C->env()->failing()) + return; + %} + + // Second node of expanded dynamic call - the call. + enc_class enc_java_dynamic_call_sched(method meth) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_bl); + + MacroAssembler _masm(&cbuf); + + if (!ra_->C->in_scratch_emit_size()) { + // Create a call trampoline stub for the given method. + const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method; + const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none); + const int entry_point_const_toc_offset = __ offset_to_method_toc(entry_point_const); + emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset()); + + if (ra_->C->env()->failing()) + return; + + // Build relocation at call site with ic position as data. + assert((_load_ic_hi_node != NULL && _load_ic_node == NULL) || + (_load_ic_hi_node == NULL && _load_ic_node != NULL), + "must have one, but can't have both"); + assert((_load_ic_hi_node != NULL && _load_ic_hi_node->_cbuf_insts_offset != -1) || + (_load_ic_node != NULL && _load_ic_node->_cbuf_insts_offset != -1), + "must contain instruction offset"); + const int virtual_call_oop_addr_offset = _load_ic_hi_node != NULL + ? _load_ic_hi_node->_cbuf_insts_offset + : _load_ic_node->_cbuf_insts_offset; + const address virtual_call_oop_addr = __ addr_at(virtual_call_oop_addr_offset); + assert(MacroAssembler::is_load_const_from_method_toc_at(virtual_call_oop_addr), + "should be load from TOC"); + + __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr)); + } + + // At this point I do not have the address of the trampoline stub, + // and the entry point might be too far away for bl. Pc() serves + // as dummy and bl will be patched later. + __ bl((address) __ pc()); + %} + + // postalloc expand emitter for virtual calls. + enc_class postalloc_expand_java_dynamic_call_sched(method meth, iRegLdst toc) %{ + // Toc is in return address field, though not accessible via postalloc_expand + // functionaliy. + Node *toc = in(TypeFunc::ReturnAdr); + + // Create the nodes for loading the IC from the TOC. + loadConLNodesTuple loadConLNodes_IC = + loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong)Universe::non_oop_word()), + OptoReg::Name(R19_H_num), OptoReg::Name(R19_num)); + + // Create the call node. + CallDynamicJavaDirectSchedNode *call = new (C) CallDynamicJavaDirectSchedNode(); + call->_method_handle_invoke = _method_handle_invoke; + call->_vtable_index = _vtable_index; + call->_method = _method; + call->_bci = _bci; + call->_optimized_virtual = _optimized_virtual; + 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; + call->_in_rms = _in_rms; + call->_nesting = _nesting; + + // New call needs all inputs of old call. + // Req... + for (uint i = 0; i < req(); ++i) { + if (i != TypeFunc::ReturnAdr) { + call->add_req(in(i)); + } else { + // The expanded node does not need toc any more. + call->add_req(C->top()); + } + } + // ...as well as prec + for (uint i = req(); i < len() ; ++i) { + call->add_prec(in(i)); + } + + // The cache must come before the call, but it's not a req edge. + // GL: actually it should be a req edge to express that the + // register must be live in the Call. But as R19 is declared to be + // the inline_cache_reg that's fine. + call->add_prec(loadConLNodes_IC._last); + // Remember nodes loading the inline cache into r19. + call->_load_ic_hi_node = loadConLNodes_IC._large_hi; + call->_load_ic_node = loadConLNodes_IC._small; + + // Operands for new nodes. + call->_opnds[0] = _opnds[0]; + call->_opnds[1] = _opnds[1]; + + // Only the inline cache is associated with a register. + assert(Matcher::inline_cache_reg() == OptoReg::Name(R19_num), "ic reg should be R19"); + + // Push new nodes. + if (loadConLNodes_IC._large_hi) nodes->push(loadConLNodes_IC._large_hi); + if (loadConLNodes_IC._last) nodes->push(loadConLNodes_IC._last); + nodes->push(call); + %} + + // Compound version of call dynamic + enc_class enc_java_dynamic_call(method meth, iRegLdst toc) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + MacroAssembler _masm(&cbuf); + int start_offset = __ offset(); + + Register Rtoc = (ra_) ? $constanttablebase : R2_TOC; +#if 0 + if (_vtable_index < 0) { + // Must be invalid_vtable_index, not nonvirtual_vtable_index. + assert(_vtable_index == Method::invalid_vtable_index, "correct sentinel value"); + Register ic_reg = as_Register(Matcher::inline_cache_reg_encode()); + AddressLiteral oop = __ allocate_metadata_address((Metadata *)Universe::non_oop_word()); + + address virtual_call_oop_addr = __ pc(); + __ load_const_from_method_toc(ic_reg, oop, Rtoc); + // CALL to fixup routine. Fixup routine uses ScopeDesc info + // to determine who we intended to call. + __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr)); + emit_call_with_trampoline_stub(_masm, (address)$meth$$method, relocInfo::none); + assert(((MachCallDynamicJavaNode*)this)->ret_addr_offset() == __ offset() - start_offset, + "Fix constant in ret_addr_offset()"); + } else { + assert(!UseInlineCaches, "expect vtable calls only if not using ICs"); + // Go thru the vtable. Get receiver klass. Receiver already + // checked for non-null. If we'll go thru a C2I adapter, the + // interpreter expects method in R19_method. + + __ load_klass(R11_scratch1, R3); + + int entry_offset = InstanceKlass::vtable_start_offset() + _vtable_index * vtableEntry::size(); + int v_off = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); + __ li(R19_method, v_off); + __ ldx(R19_method/*method oop*/, R19_method/*method offset*/, R11_scratch1/*class*/); + // NOTE: for vtable dispatches, the vtable entry will never be + // null. However it may very well end up in handle_wrong_method + // if the method is abstract for the particular class. + __ ld(R11_scratch1, in_bytes(Method::from_compiled_offset()), R19_method); + // Call target. Either compiled code or C2I adapter. + __ mtctr(R11_scratch1); + __ bctrl(); + if (((MachCallDynamicJavaNode*)this)->ret_addr_offset() != __ offset() - start_offset) { + tty->print(" %d, %d\n", ((MachCallDynamicJavaNode*)this)->ret_addr_offset(),__ offset() - start_offset); + } + assert(((MachCallDynamicJavaNode*)this)->ret_addr_offset() == __ offset() - start_offset, + "Fix constant in ret_addr_offset()"); + } +#endif + Unimplemented(); // ret_addr_offset not yet fixed. Depends on compressed oops (load klass!). + %} + + // a runtime call + enc_class enc_java_to_runtime_call (method meth) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + + MacroAssembler _masm(&cbuf); + const address start_pc = __ pc(); + + // The function we're going to call. + FunctionDescriptor fdtemp; + const FunctionDescriptor* fd = !($meth$$method) ? &fdtemp : (FunctionDescriptor*)$meth$$method; + + Register Rtoc = R12_scratch2; + // Calculate the method's TOC. + __ calculate_address_from_global_toc(Rtoc, __ method_toc()); + // Put entry, env, toc into the constant pool, this needs up to 3 constant + // pool entries; call_c_using_toc will optimize the call. + __ call_c_using_toc(fd, relocInfo::runtime_call_type, Rtoc); + + // Check the ret_addr_offset. + assert(((MachCallRuntimeNode*)this)->ret_addr_offset() == __ last_calls_return_pc() - start_pc, + "Fix constant in ret_addr_offset()"); + %} + + // Move to ctr for leaf call. + // 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); + MacroAssembler _masm(&cbuf); + __ mtctr($src$$Register); + %} + + // postalloc expand emitter for runtime leaf calls. + enc_class postalloc_expand_java_to_runtime_call(method meth, iRegLdst toc) %{ + // Get the struct that describes the function we are about to call. + FunctionDescriptor* fd = (FunctionDescriptor*) this->entry_point(); + assert(fd, "need fd here"); + // new nodes + loadConLNodesTuple loadConLNodes_Entry; + loadConLNodesTuple loadConLNodes_Env; + loadConLNodesTuple loadConLNodes_Toc; + MachNode *mtctr = NULL; + MachCallLeafNode *call = NULL; + + // Create nodes and operands for loading the entry point. + loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong) fd->entry()), + OptoReg::Name(R12_H_num), OptoReg::Name(R12_num)); + + + // Create nodes and operands for loading the env pointer. + if (fd->env() != NULL) { + loadConLNodes_Env = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong) fd->env()), + OptoReg::Name(R11_H_num), OptoReg::Name(R11_num)); + } else { + loadConLNodes_Env._large_hi = NULL; + loadConLNodes_Env._large_lo = NULL; + loadConLNodes_Env._small = NULL; + loadConLNodes_Env._last = new (C) loadConL16Node(); + loadConLNodes_Env._last->_opnds[0] = new (C) iRegLdstOper(); + loadConLNodes_Env._last->_opnds[1] = new (C) immL16Oper(0); + ra_->set_pair(loadConLNodes_Env._last->_idx, OptoReg::Name(R11_H_num), OptoReg::Name(R11_num)); + } + + // Create nodes and operands for loading the Toc point. + loadConLNodes_Toc = loadConLNodesTuple_create(C, ra_, n_toc, new (C) immLOper((jlong) fd->toc()), + OptoReg::Name(R2_H_num), OptoReg::Name(R2_num)); + // mtctr node + mtctr = new (C) CallLeafDirect_mtctrNode(); + + assert(loadConLNodes_Entry._last != NULL, "entry must exist"); + mtctr->add_req(0, loadConLNodes_Entry._last); + + mtctr->_opnds[0] = new (C) iRegLdstOper(); + mtctr->_opnds[1] = new (C) iRegLdstOper(); + + // call node + call = new (C) CallLeafDirectNode(); + + call->_opnds[0] = _opnds[0]; + call->_opnds[1] = new (C) methodOper((intptr_t) fd->entry()); // may get set later + + // Make the new call node look like the old one. + call->_name = _name; + 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; + call->_jvmadj = _jvmadj; + call->_in_rms = _in_rms; + call->_nesting = _nesting; + + + // New call needs all inputs of old call. + // Req... + for (uint i = 0; i < req(); ++i) { + if (i != TypeFunc::ReturnAdr) { + call->add_req(in(i)); + } else { + // put the mtctr where ReturnAdr would be + call->add_req(mtctr); + } + } + + // These must be reqired edges, as the registers are live up to + // the call. Else the constants are handled as kills. + call->add_req(loadConLNodes_Env._last); + call->add_req(loadConLNodes_Toc._last); + + // ...as well as prec + for (uint i = req(); i < len(); ++i) { + call->add_prec(in(i)); + } + + // registers + ra_->set1(mtctr->_idx, OptoReg::Name(SR_CTR_num)); + + // Insert the new nodes. + if (loadConLNodes_Entry._large_hi) nodes->push(loadConLNodes_Entry._large_hi); + if (loadConLNodes_Entry._last) nodes->push(loadConLNodes_Entry._last); + if (loadConLNodes_Env._large_hi) nodes->push(loadConLNodes_Env._large_hi); + if (loadConLNodes_Env._last) nodes->push(loadConLNodes_Env._last); + if (loadConLNodes_Toc._large_hi) nodes->push(loadConLNodes_Toc._large_hi); + if (loadConLNodes_Toc._last) nodes->push(loadConLNodes_Toc._last); + nodes->push(mtctr); + nodes->push(call); + %} +%} + +//----------FRAME-------------------------------------------------------------- +// 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 methodOop for I2C. + inline_cache_reg(R19); // R19_method + + // Method Oop Register when calling interpreter. + interpreter_method_oop_reg(R19); // R19_method + + // Optional: name the operand used by cisc-spilling to access + // [stack_pointer + offset]. + cisc_spilling_operand_name(indOffset); + + // Number of stack slots consumed by a Monitor enter. + sync_stack_slots((frame::jit_monitor_size / VMRegImpl::stack_slot_size)); + + // Compiled code's Frame Pointer. + frame_pointer(R1); // R1_SP + + // Interpreter stores its frame pointer in a register which is + // stored to the stack by I2CAdaptors. I2CAdaptors convert from + // interpreted java to compiled java. + // + // R14_state holds pointer to caller's cInterpreter. + interpreter_frame_pointer(R14); // R14_state + + stack_alignment(frame::alignment_in_bytes); + + in_preserve_stack_slots((frame::jit_in_preserve_size / VMRegImpl::stack_slot_size)); + + // Number of outgoing stack slots killed above the + // out_preserve_stack_slots for calls to C. Supports the var-args + // backing area for register parms. + // + varargs_C_out_slots_killed(((frame::abi_112_size - frame::jit_out_preserve_size) / VMRegImpl::stack_slot_size)); + + // The after-PROLOG location of the return address. Location of + // return address specifies a type (REG or STACK) and a number + // representing the register number (i.e. - use a register name) or + // stack slot. + // + // A: Link register is stored in stack slot ... + // M: ... but it's in the caller's frame according to PPC-64 ABI. + // J: Therefore, we make sure that the link register is also in R11_scratch1 + // at the end of the prolog. + // B: We use R20, now. + //return_addr(REG R20); + + // G: After reading the comments made by all the luminaries on their + // failure to tell the compiler where the return address really is, + // I hardly dare to try myself. However, I'm convinced it's in slot + // 4 what apparently works and saves us some spills. + return_addr(STACK 4); + + // This is the body of the function + // + // void Matcher::calling_convention(OptoRegPair* sig, // array of ideal regs + // uint length, // length of array + // bool is_outgoing) + // + // The `sig' array is to be updated. sig[j] represents the location + // of the j-th argument, either a register or a stack slot. + + // Comment taken from i486.ad: + // Body of function which returns an integer array locating + // arguments either in registers or in stack slots. Passed an array + // of ideal registers called "sig" and a "length" count. Stack-slot + // offsets are based on outgoing arguments, i.e. a CALLER setting up + // arguments for a CALLEE. Incoming stack arguments are + // automatically biased by the preserve_stack_slots field above. + calling_convention %{ + // No difference between ingoing/outgoing. Just pass false. + SharedRuntime::java_calling_convention(sig_bt, regs, length, false); + %} + + // Comment taken from i486.ad: + // Body of function which returns an integer array locating + // arguments either in registers or in stack slots. Passed an array + // of ideal registers called "sig" and a "length" count. Stack-slot + // offsets are based on outgoing arguments, i.e. a CALLER setting up + // arguments for a CALLEE. Incoming stack arguments are + // automatically biased by the preserve_stack_slots field above. + c_calling_convention %{ + // This is obviously always outgoing. + // C argument in register AND stack slot. + (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); + %} + + // Location of native (C/C++) and interpreter return values. This + // is specified to be the same as Java. In the 32-bit VM, long + // values are actually returned from native calls in O0:O1 and + // returned to the interpreter in I0:I1. The copying to and from + // the register pairs is done by the appropriate call and epilog + // opcodes. This simplifies the register allocator. + c_return_value %{ + assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || + (ideal_reg == Op_RegN && Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0), + "only return normal values"); + // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL + static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; + static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; + return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); + %} + + // Location of compiled Java return values. Same as C + return_value %{ + assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || + (ideal_reg == Op_RegN && Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0), + "only return normal values"); + // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL + static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; + static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; + return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); + %} +%} + + +//----------ATTRIBUTES--------------------------------------------------------- + +//----------Operand Attributes------------------------------------------------- +op_attrib op_cost(1); // Required cost attribute. + +//----------Instruction Attributes--------------------------------------------- + +// Cost attribute. required. +ins_attrib ins_cost(DEFAULT_COST); + +// Is this instruction a non-matching short branch variant of some +// long branch? Not required. +ins_attrib ins_short_branch(0); + +// This instruction does implicit checks at the given machine-instruction offset +// (optional attribute). +ins_attrib ins_implicit_check_offset(-1); // TODO: PPC port + +ins_attrib ins_implicit_check_follows_matched_true_path(true); +ins_attrib ins_is_TrapBasedCheckNode(true); + +// Number of constants. +// This instruction uses the given number of constants +// (optional attribute). +// This is needed to determine in time whether the constant pool will +// exceed 4000 entries. Before postalloc_expand the overall number of constants +// is determined. It's also used to compute the constant pool size +// in Output(). +ins_attrib ins_num_consts(0); + +// Required alignment attribute (must be a power of 2) specifies the +// alignment that some part of the instruction (not necessarily the +// start) requires. If > 1, a compute_padding() function must be +// provided for the instruction. +ins_attrib ins_alignment(1); + +// Enforce/prohibit rematerializations. +// - If an instruction is attributed with 'ins_cannot_rematerialize(true)' +// then rematerialization of that instruction is prohibited and the +// instruction's value will be spilled if necessary. +// Causes that MachNode::rematerialize() returns false. +// - If an instruction is attributed with 'ins_should_rematerialize(true)' +// then rematerialization should be enforced and a copy of the instruction +// should be inserted if possible; rematerialization is not guaranteed. +// Note: this may result in rematerializations in front of every use. +// Causes that MachNode::rematerialize() can return true. +// (optional attribute) +ins_attrib ins_cannot_rematerialize(false); +ins_attrib ins_should_rematerialize(false); + +// Instruction has variable size depending on alignment. +ins_attrib ins_variable_size_depending_on_alignment(false); + +// Instruction is a nop. +ins_attrib ins_is_nop(false); + +// Instruction is mapped to a MachIfFastLock node (instead of MachFastLock). +ins_attrib ins_use_mach_if_fast_lock_node(false); + +// Field for the toc offset of a constant. +// +// This is needed if the toc offset is not encodable as an immediate in +// the PPC load instruction. If so, the upper (hi) bits of the offset are +// added to the toc, and from this a load with immediate is performed. +// With postalloc expand, we get two nodes that require the same offset +// but which don't know about each other. The offset is only known +// when the constant is added to the constant pool during emitting. +// It is generated in the 'hi'-node adding the upper bits, and saved +// in this node. The 'lo'-node has a link to the 'hi'-node and reads +// the offset from there when it gets encoded. +ins_attrib ins_field_const_toc_offset(0); +ins_attrib ins_field_const_toc_offset_hi_node(0); + +// A field that can hold the instructions offset in the code buffer. +// Set in the nodes emitter. +ins_attrib ins_field_cbuf_insts_offset(-1); + +// Fields for referencing a call's load-IC-node. +// If the toc offset can not be encoded as an immediate in a load, we +// use two nodes. +ins_attrib ins_field_load_ic_hi_node(0); +ins_attrib ins_field_load_ic_node(0); + +//----------OPERANDS----------------------------------------------------------- +// Operand definitions must precede instruction definitions for correct +// parsing in the ADLC because operands constitute user defined types +// which are used in instruction definitions. +// +// Formats are generated automatically for constants and base registers. + +//----------Simple Operands---------------------------------------------------- +// Immediate Operands + +// Integer Immediate: 32-bit +operand immI() %{ + match(ConI); + op_cost(40); + format %{ %} + interface(CONST_INTER); +%} + +operand immI8() %{ + predicate(Assembler::is_simm(n->get_int(), 8)); + op_cost(0); + match(ConI); + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: 16-bit +operand immI16() %{ + predicate(Assembler::is_simm(n->get_int(), 16)); + op_cost(0); + match(ConI); + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: 32-bit, where lowest 16 bits are 0x0000. +operand immIhi16() %{ + predicate(((n->get_int() & 0xffff0000) != 0) && ((n->get_int() & 0xffff) == 0)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immInegpow2() %{ + predicate(is_power_of_2_long((jlong) (julong) (juint) (-(n->get_int())))); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immIpow2minus1() %{ + predicate(is_power_of_2_long((((jlong) (n->get_int()))+1))); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immIpowerOf2() %{ + predicate(is_power_of_2_long((((jlong) (julong) (juint) (n->get_int()))))); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: the values 0-31 +operand uimmI5() %{ + predicate(Assembler::is_uimm(n->get_int(), 5)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 6-bit +operand uimmI6() %{ + predicate(Assembler::is_uimm(n->get_int(), 6)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 6-bit int, greater than 32 +operand uimmI6_ge32() %{ + predicate(Assembler::is_uimm(n->get_int(), 6) && n->get_int() >= 32); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 15-bit +operand uimmI15() %{ + predicate(Assembler::is_uimm(n->get_int(), 15)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 16-bit +operand uimmI16() %{ + predicate(Assembler::is_uimm(n->get_int(), 16)); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// constant 'int 0'. +operand immI_0() %{ + predicate(n->get_int() == 0); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// constant 'int 1'. +operand immI_1() %{ + predicate(n->get_int() == 1); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// constant 'int -1'. +operand immI_minus1() %{ + predicate(n->get_int() == -1); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// int value 16. +operand immI_16() %{ + predicate(n->get_int() == 16); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// int value 24. +operand immI_24() %{ + predicate(n->get_int() == 24); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Compressed oops constants +// Pointer Immediate +operand immN() %{ + match(ConN); + + op_cost(10); + format %{ %} + interface(CONST_INTER); +%} + +// NULL Pointer Immediate +operand immN_0() %{ + predicate(n->get_narrowcon() == 0); + match(ConN); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Compressed klass constants +operand immNKlass() %{ + match(ConNKlass); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// This operand can be used to avoid matching of an instruct +// with chain rule. +operand immNKlass_NM() %{ + match(ConNKlass); + predicate(false); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Pointer Immediate: 64-bit +operand immP() %{ + match(ConP); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Operand to avoid match of loadConP. +// This operand can be used to avoid matching of an instruct +// with chain rule. +operand immP_NM() %{ + match(ConP); + predicate(false); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// costant 'pointer 0'. +operand immP_0() %{ + predicate(n->get_ptr() == 0); + match(ConP); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// pointer 0x0 or 0x1 +operand immP_0or1() %{ + predicate((n->get_ptr() == 0) || (n->get_ptr() == 1)); + match(ConP); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immL() %{ + match(ConL); + op_cost(40); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: 16-bit +operand immL16() %{ + predicate(Assembler::is_simm(n->get_long(), 16)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: 16-bit, 4-aligned +operand immL16Alg4() %{ + predicate(Assembler::is_simm(n->get_long(), 16) && ((n->get_long() & 0x3) == 0)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: 32-bit, where lowest 16 bits are 0x0000. +operand immL32hi16() %{ + predicate(Assembler::is_simm(n->get_long(), 32) && ((n->get_long() & 0xffffL) == 0L)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: 32-bit +operand immL32() %{ + predicate(Assembler::is_simm(n->get_long(), 32)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: 64-bit, where highest 16 bits are not 0x0000. +operand immLhighest16() %{ + predicate((n->get_long() & 0xffff000000000000L) != 0L && (n->get_long() & 0x0000ffffffffffffL) == 0L); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immLnegpow2() %{ + predicate(is_power_of_2_long((jlong)-(n->get_long()))); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +operand immLpow2minus1() %{ + predicate(is_power_of_2_long((((jlong) (n->get_long()))+1)) && + (n->get_long() != (jlong)0xffffffffffffffffL)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// constant 'long 0'. +operand immL_0() %{ + predicate(n->get_long() == 0L); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// constat ' long -1'. +operand immL_minus1() %{ + predicate(n->get_long() == -1L); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: low 32-bit mask +operand immL_32bits() %{ + predicate(n->get_long() == 0xFFFFFFFFL); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Long Immediate: 16-bit +operand uimmL16() %{ + predicate(Assembler::is_uimm(n->get_long(), 16)); + match(ConL); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Float Immediate +operand immF() %{ + match(ConF); + op_cost(40); + format %{ %} + interface(CONST_INTER); +%} + +// constant 'float +0.0'. +operand immF_0() %{ + predicate((n->getf() == 0) && + (fpclassify(n->getf()) == FP_ZERO) && (signbit(n->getf()) == 0)); + match(ConF); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Double Immediate +operand immD() %{ + match(ConD); + op_cost(40); + format %{ %} + interface(CONST_INTER); +%} + +// Integer Register Operands +// Integer Destination Register +// See definition of reg_class bits32_reg_rw. +operand iRegIdst() %{ + constraint(ALLOC_IN_RC(bits32_reg_rw)); + match(RegI); + match(rscratch1RegI); + match(rscratch2RegI); + match(rarg1RegI); + match(rarg2RegI); + match(rarg3RegI); + match(rarg4RegI); + format %{ %} + interface(REG_INTER); +%} + +// Integer Source Register +// See definition of reg_class bits32_reg_ro. +operand iRegIsrc() %{ + constraint(ALLOC_IN_RC(bits32_reg_ro)); + match(RegI); + match(rscratch1RegI); + match(rscratch2RegI); + match(rarg1RegI); + match(rarg2RegI); + match(rarg3RegI); + match(rarg4RegI); + format %{ %} + interface(REG_INTER); +%} + +operand rscratch1RegI() %{ + constraint(ALLOC_IN_RC(rscratch1_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rscratch2RegI() %{ + constraint(ALLOC_IN_RC(rscratch2_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg1RegI() %{ + constraint(ALLOC_IN_RC(rarg1_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg2RegI() %{ + constraint(ALLOC_IN_RC(rarg2_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg3RegI() %{ + constraint(ALLOC_IN_RC(rarg3_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg4RegI() %{ + constraint(ALLOC_IN_RC(rarg4_bits32_reg)); + match(iRegIdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg1RegL() %{ + constraint(ALLOC_IN_RC(rarg1_bits64_reg)); + match(iRegLdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg2RegL() %{ + constraint(ALLOC_IN_RC(rarg2_bits64_reg)); + match(iRegLdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg3RegL() %{ + constraint(ALLOC_IN_RC(rarg3_bits64_reg)); + match(iRegLdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg4RegL() %{ + constraint(ALLOC_IN_RC(rarg4_bits64_reg)); + match(iRegLdst); + format %{ %} + interface(REG_INTER); +%} + +// Pointer Destination Register +// See definition of reg_class bits64_reg_rw. +operand iRegPdst() %{ + constraint(ALLOC_IN_RC(bits64_reg_rw)); + match(RegP); + match(rscratch1RegP); + match(rscratch2RegP); + match(rarg1RegP); + match(rarg2RegP); + match(rarg3RegP); + match(rarg4RegP); + format %{ %} + interface(REG_INTER); +%} + +// Pointer Destination Register +// Operand not using r11 and r12 (killed in epilog). +operand iRegPdstNoScratch() %{ + constraint(ALLOC_IN_RC(bits64_reg_leaf_call)); + match(RegP); + match(rarg1RegP); + match(rarg2RegP); + match(rarg3RegP); + match(rarg4RegP); + format %{ %} + interface(REG_INTER); +%} + +// Pointer Source Register +// See definition of reg_class bits64_reg_ro. +operand iRegPsrc() %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(RegP); + match(iRegPdst); + match(rscratch1RegP); + match(rscratch2RegP); + match(rarg1RegP); + match(rarg2RegP); + match(rarg3RegP); + match(rarg4RegP); + match(threadRegP); + format %{ %} + interface(REG_INTER); +%} + +// Thread operand. +operand threadRegP() %{ + constraint(ALLOC_IN_RC(thread_bits64_reg)); + match(iRegPdst); + format %{ "R16" %} + interface(REG_INTER); +%} + +operand rscratch1RegP() %{ + constraint(ALLOC_IN_RC(rscratch1_bits64_reg)); + match(iRegPdst); + format %{ "R11" %} + interface(REG_INTER); +%} + +operand rscratch2RegP() %{ + constraint(ALLOC_IN_RC(rscratch2_bits64_reg)); + match(iRegPdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg1RegP() %{ + constraint(ALLOC_IN_RC(rarg1_bits64_reg)); + match(iRegPdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg2RegP() %{ + constraint(ALLOC_IN_RC(rarg2_bits64_reg)); + match(iRegPdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg3RegP() %{ + constraint(ALLOC_IN_RC(rarg3_bits64_reg)); + match(iRegPdst); + format %{ %} + interface(REG_INTER); +%} + +operand rarg4RegP() %{ + constraint(ALLOC_IN_RC(rarg4_bits64_reg)); + match(iRegPdst); + format %{ %} + interface(REG_INTER); +%} + +operand iRegNsrc() %{ + constraint(ALLOC_IN_RC(bits32_reg_ro)); + match(RegN); + match(iRegNdst); + + format %{ %} + interface(REG_INTER); +%} + +operand iRegNdst() %{ + constraint(ALLOC_IN_RC(bits32_reg_rw)); + match(RegN); + + format %{ %} + interface(REG_INTER); +%} + +// Long Destination Register +// See definition of reg_class bits64_reg_rw. +operand iRegLdst() %{ + constraint(ALLOC_IN_RC(bits64_reg_rw)); + match(RegL); + match(rscratch1RegL); + match(rscratch2RegL); + format %{ %} + interface(REG_INTER); +%} + +// Long Source Register +// See definition of reg_class bits64_reg_ro. +operand iRegLsrc() %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(RegL); + match(iRegLdst); + match(rscratch1RegL); + match(rscratch2RegL); + format %{ %} + interface(REG_INTER); +%} + +// Special operand for ConvL2I. +operand iRegL2Isrc(iRegLsrc reg) %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(ConvL2I reg); + format %{ "ConvL2I($reg)" %} + interface(REG_INTER) +%} + +operand rscratch1RegL() %{ + constraint(ALLOC_IN_RC(rscratch1_bits64_reg)); + match(RegL); + format %{ %} + interface(REG_INTER); +%} + +operand rscratch2RegL() %{ + constraint(ALLOC_IN_RC(rscratch2_bits64_reg)); + match(RegL); + format %{ %} + interface(REG_INTER); +%} + +// Condition Code Flag Registers +operand flagsReg() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ %} + interface(REG_INTER); +%} + +// Condition Code Flag Register CR0 +operand flagsRegCR0() %{ + constraint(ALLOC_IN_RC(int_flags_CR0)); + match(RegFlags); + format %{ "CR0" %} + interface(REG_INTER); +%} + +operand flagsRegCR1() %{ + constraint(ALLOC_IN_RC(int_flags_CR1)); + match(RegFlags); + format %{ "CR1" %} + interface(REG_INTER); +%} + +operand flagsRegCR6() %{ + constraint(ALLOC_IN_RC(int_flags_CR6)); + match(RegFlags); + format %{ "CR6" %} + interface(REG_INTER); +%} + +operand regCTR() %{ + constraint(ALLOC_IN_RC(ctr_reg)); + // RegFlags should work. Introducing a RegSpecial type would cause a + // lot of changes. + match(RegFlags); + format %{"SR_CTR" %} + interface(REG_INTER); +%} + +operand regD() %{ + constraint(ALLOC_IN_RC(dbl_reg)); + match(RegD); + format %{ %} + interface(REG_INTER); +%} + +operand regF() %{ + constraint(ALLOC_IN_RC(flt_reg)); + match(RegF); + format %{ %} + interface(REG_INTER); +%} + +// Special Registers + +// Method Register +operand inline_cache_regP(iRegPdst reg) %{ + constraint(ALLOC_IN_RC(r19_bits64_reg)); // inline_cache_reg + match(reg); + format %{ %} + interface(REG_INTER); +%} + +operand compiler_method_oop_regP(iRegPdst reg) %{ + constraint(ALLOC_IN_RC(rscratch1_bits64_reg)); // compiler_method_oop_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 + match(reg); + format %{ %} + interface(REG_INTER); +%} + +// Operands to remove register moves in unscaled mode. +// Match read/write registers with an EncodeP node if neither shift nor add are required. +operand iRegP2N(iRegPsrc reg) %{ + predicate(false /* TODO: PPC port MatchDecodeNodes*/&& Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(EncodeP reg); + format %{ "$reg" %} + interface(REG_INTER) +%} + +operand iRegN2P(iRegNsrc reg) %{ + predicate(false /* TODO: PPC port MatchDecodeNodes*/); + constraint(ALLOC_IN_RC(bits32_reg_ro)); + match(DecodeN reg); + match(DecodeNKlass reg); + format %{ "$reg" %} + interface(REG_INTER) +%} + +//----------Complex Operands--------------------------------------------------- +// Indirect Memory Reference +operand indirect(iRegPsrc reg) %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(reg); + op_cost(100); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp(0x0); + %} +%} + +// Indirect with Offset +operand indOffset16(iRegPsrc reg, immL16 offset) %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(AddP reg offset); + op_cost(100); + format %{ "[$reg + $offset]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp($offset); + %} +%} + +// Indirect with 4-aligned Offset +operand indOffset16Alg4(iRegPsrc reg, immL16Alg4 offset) %{ + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(AddP reg offset); + op_cost(100); + format %{ "[$reg + $offset]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp($offset); + %} +%} + +//----------Complex Operands for Compressed OOPs------------------------------- +// Compressed OOPs with narrow_oop_shift == 0. + +// Indirect Memory Reference, compressed OOP +operand indirectNarrow(iRegNsrc reg) %{ + predicate(false /* TODO: PPC port MatchDecodeNodes*/); + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(DecodeN reg); + match(DecodeNKlass reg); + op_cost(100); + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp(0x0); + %} +%} + +// Indirect with Offset, compressed OOP +operand indOffset16Narrow(iRegNsrc reg, immL16 offset) %{ + predicate(false /* TODO: PPC port MatchDecodeNodes*/); + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(AddP (DecodeN reg) offset); + match(AddP (DecodeNKlass reg) offset); + op_cost(100); + format %{ "[$reg + $offset]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp($offset); + %} +%} + +// Indirect with 4-aligned Offset, compressed OOP +operand indOffset16NarrowAlg4(iRegNsrc reg, immL16Alg4 offset) %{ + predicate(false /* TODO: PPC port MatchDecodeNodes*/); + constraint(ALLOC_IN_RC(bits64_reg_ro)); + match(AddP (DecodeN reg) offset); + match(AddP (DecodeNKlass reg) offset); + op_cost(100); + format %{ "[$reg + $offset]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x0); + scale(0x0); + disp($offset); + %} +%} + +//----------Special Memory Operands-------------------------------------------- +// Stack Slot Operand +// +// This operand is used for loading and storing temporary values on +// the stack where a match requires a value to flow through memory. +operand stackSlotI(sRegI reg) %{ + constraint(ALLOC_IN_RC(stack_slots)); + op_cost(100); + //match(RegI); + format %{ "[sp+$reg]" %} + interface(MEMORY_INTER) %{ + base(0x1); // R1_SP + index(0x0); + scale(0x0); + disp($reg); // Stack Offset + %} +%} + +operand stackSlotL(sRegL reg) %{ + constraint(ALLOC_IN_RC(stack_slots)); + op_cost(100); + //match(RegL); + format %{ "[sp+$reg]" %} + interface(MEMORY_INTER) %{ + base(0x1); // R1_SP + index(0x0); + scale(0x0); + disp($reg); // Stack Offset + %} +%} + +operand stackSlotP(sRegP reg) %{ + constraint(ALLOC_IN_RC(stack_slots)); + op_cost(100); + //match(RegP); + format %{ "[sp+$reg]" %} + interface(MEMORY_INTER) %{ + base(0x1); // R1_SP + index(0x0); + scale(0x0); + disp($reg); // Stack Offset + %} +%} + +operand stackSlotF(sRegF reg) %{ + constraint(ALLOC_IN_RC(stack_slots)); + op_cost(100); + //match(RegF); + format %{ "[sp+$reg]" %} + interface(MEMORY_INTER) %{ + base(0x1); // R1_SP + index(0x0); + scale(0x0); + disp($reg); // Stack Offset + %} +%} + +operand stackSlotD(sRegD reg) %{ + constraint(ALLOC_IN_RC(stack_slots)); + op_cost(100); + //match(RegD); + format %{ "[sp+$reg]" %} + interface(MEMORY_INTER) %{ + base(0x1); // R1_SP + index(0x0); + scale(0x0); + disp($reg); // Stack Offset + %} +%} + +// Operands for expressing Control Flow +// NOTE: Label is a predefined operand which should not be redefined in +// the AD file. It is generically handled within the ADLC. + +//----------Conditional Branch Operands---------------------------------------- +// Comparison Op +// +// This is the operation of the comparison, and is limited to the +// following set of codes: L (<), LE (<=), G (>), GE (>=), E (==), NE +// (!=). +// +// Other attributes of the comparison, such as unsignedness, are specified +// by the comparison instruction that sets a condition code flags register. +// That result is represented by a flags operand whose subtype is appropriate +// to the unsignedness (etc.) of the comparison. +// +// Later, the instruction which matches both the Comparison Op (a Bool) and +// the flags (produced by the Cmp) specifies the coding of the comparison op +// by matching a specific subtype of Bool operand below. + +// When used for floating point comparisons: unordered same as less. +operand cmpOp() %{ + match(Bool); + format %{ "" %} + interface(COND_INTER) %{ + // BO only encodes bit 4 of bcondCRbiIsX, as bits 1-3 are always '100'. + // BO & BI + equal(0xA); // 10 10: bcondCRbiIs1 & Condition::equal + not_equal(0x2); // 00 10: bcondCRbiIs0 & Condition::equal + less(0x8); // 10 00: bcondCRbiIs1 & Condition::less + greater_equal(0x0); // 00 00: bcondCRbiIs0 & Condition::less + less_equal(0x1); // 00 01: bcondCRbiIs0 & Condition::greater + greater(0x9); // 10 01: bcondCRbiIs1 & Condition::greater + overflow(0xB); // 10 11: bcondCRbiIs1 & Condition::summary_overflow + no_overflow(0x3); // 00 11: bcondCRbiIs0 & Condition::summary_overflow + %} +%} + +//----------OPERAND CLASSES---------------------------------------------------- +// Operand Classes are groups of operands that are used to simplify +// instruction definitions by not requiring the AD writer to specify +// seperate instructions for every form of operand when the +// instruction accepts multiple operand types with the same basic +// encoding and format. The classic case of this is memory operands. +// Indirect is not included since its use is limited to Compare & Swap. + +opclass memory(indirect, indOffset16 /*, indIndex, tlsReference*/, indirectNarrow, indOffset16Narrow); +// Memory operand where offsets are 4-aligned. Required for ld, std. +opclass memoryAlg4(indirect, indOffset16Alg4, indirectNarrow, indOffset16NarrowAlg4); +opclass indirectMemory(indirect, indirectNarrow); + +// Special opclass for I and ConvL2I. +opclass iRegIsrc_iRegL2Isrc(iRegIsrc, iRegL2Isrc); + +// Operand classes to match encode and decode. iRegN_P2N is only used +// for storeN. I have never seen an encode node elsewhere. +opclass iRegN_P2N(iRegNsrc, iRegP2N); +opclass iRegP_N2P(iRegPsrc, iRegN2P); + +//----------PIPELINE----------------------------------------------------------- + +pipeline %{ + +// See J.M.Tendler et al. "Power4 system microarchitecture", IBM +// J. Res. & Dev., No. 1, Jan. 2002. + +//----------ATTRIBUTES--------------------------------------------------------- +attributes %{ + + // Power4 instructions are of fixed length. + fixed_size_instructions; + + // TODO: if `bundle' means number of instructions fetched + // per cycle, this is 8. If `bundle' means Power4 `group', that is + // max instructions issued per cycle, this is 5. + max_instructions_per_bundle = 8; + + // A Power4 instruction is 4 bytes long. + instruction_unit_size = 4; + + // The Power4 processor fetches 64 bytes... + instruction_fetch_unit_size = 64; + + // ...in one line + instruction_fetch_units = 1 + + // Unused, list one so that array generated by adlc is not empty. + // Aix compiler chokes if _nop_count = 0. + nops(fxNop); +%} + +//----------RESOURCES---------------------------------------------------------- +// Resources are the functional units available to the machine +resources( + PPC_BR, // branch unit + PPC_CR, // condition unit + PPC_FX1, // integer arithmetic unit 1 + PPC_FX2, // integer arithmetic unit 2 + PPC_LDST1, // load/store unit 1 + PPC_LDST2, // load/store unit 2 + PPC_FP1, // float arithmetic unit 1 + PPC_FP2, // float arithmetic unit 2 + PPC_LDST = PPC_LDST1 | PPC_LDST2, + PPC_FX = PPC_FX1 | PPC_FX2, + PPC_FP = PPC_FP1 | PPC_FP2 + ); + +//----------PIPELINE DESCRIPTION----------------------------------------------- +// Pipeline Description specifies the stages in the machine's pipeline +pipe_desc( + // Power4 longest pipeline path + PPC_IF, // instruction fetch + PPC_IC, + //PPC_BP, // branch prediction + PPC_D0, // decode + PPC_D1, // decode + PPC_D2, // decode + PPC_D3, // decode + PPC_Xfer1, + PPC_GD, // group definition + PPC_MP, // map + PPC_ISS, // issue + PPC_RF, // resource fetch + PPC_EX1, // execute (all units) + PPC_EX2, // execute (FP, LDST) + PPC_EX3, // execute (FP, LDST) + PPC_EX4, // execute (FP) + PPC_EX5, // execute (FP) + PPC_EX6, // execute (FP) + PPC_WB, // write back + PPC_Xfer2, + PPC_CP + ); + +//----------PIPELINE CLASSES--------------------------------------------------- +// Pipeline Classes describe the stages in which input and output are +// referenced by the hardware pipeline. + +// Simple pipeline classes. + +// Default pipeline class. +pipe_class pipe_class_default() %{ + single_instruction; + fixed_latency(2); +%} + +// Pipeline class for empty instructions. +pipe_class pipe_class_empty() %{ + single_instruction; + fixed_latency(0); +%} + +// Pipeline class for compares. +pipe_class pipe_class_compare() %{ + single_instruction; + fixed_latency(16); +%} + +// Pipeline class for traps. +pipe_class pipe_class_trap() %{ + single_instruction; + fixed_latency(100); +%} + +// Pipeline class for memory operations. +pipe_class pipe_class_memory() %{ + single_instruction; + fixed_latency(16); +%} + +// Pipeline class for call. +pipe_class pipe_class_call() %{ + single_instruction; + fixed_latency(100); +%} + +// Define the class for the Nop node. +define %{ + MachNop = pipe_class_default; +%} + +%} + +//----------INSTRUCTIONS------------------------------------------------------- + +// Naming of instructions: +// opA_operB / opA_operB_operC: +// Operation 'op' with one or two source operands 'oper'. Result +// type is A, source operand types are B and C. +// Iff A == B == C, B and C are left out. +// +// The instructions are ordered according to the following scheme: +// - loads +// - load constants +// - prefetch +// - store +// - encode/decode +// - membar +// - conditional moves +// - compare & swap +// - arithmetic and logic operations +// * int: Add, Sub, Mul, Div, Mod +// * int: lShift, arShift, urShift, rot +// * float: Add, Sub, Mul, Div +// * and, or, xor ... +// - register moves: float <-> int, reg <-> stack, repl +// - cast (high level type cast, XtoP, castPP, castII, not_null etc. +// - conv (low level type cast requiring bit changes (sign extend etc) +// - compares, range & zero checks. +// - branches +// - complex operations, intrinsics, min, max, replicate +// - lock +// - Calls +// +// If there are similar instructions with different types they are sorted: +// int before float +// small before big +// signed before unsigned +// e.g., loadS before loadUS before loadI before loadF. + + +//----------Load/Store Instructions-------------------------------------------- + +//----------Load Instructions-------------------------------------------------- + +// Converts byte to int. +// As convB2I_reg, but without match rule. The match rule of convB2I_reg +// reuses the 'amount' operand, but adlc expects that operand specification +// and operands in match rule are equivalent. +instruct convB2I_reg_2(iRegIdst dst, iRegIsrc src) %{ + effect(DEF dst, USE 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); +%} + +instruct loadUB_indirect(iRegIdst dst, indirectMemory mem) %{ + // match-rule, false predicate + match(Set dst (LoadB mem)); + predicate(false); + + format %{ "LBZ $dst, $mem" %} + size(4); + ins_encode( enc_lbz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +instruct loadUB_indirect_ac(iRegIdst dst, indirectMemory mem) %{ + // match-rule, false predicate + match(Set dst (LoadB mem)); + predicate(false); + + format %{ "LBZ $dst, $mem\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lbz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Byte (8bit signed). LoadB = LoadUB + ConvUB2B. +instruct loadB_indirect_Ex(iRegIdst dst, indirectMemory mem) %{ + match(Set dst (LoadB mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + expand %{ + iRegIdst tmp; + loadUB_indirect(tmp, mem); + convB2I_reg_2(dst, tmp); + %} +%} + +instruct loadB_indirect_ac_Ex(iRegIdst dst, indirectMemory mem) %{ + match(Set dst (LoadB mem)); + ins_cost(3*MEMORY_REF_COST + DEFAULT_COST); + expand %{ + iRegIdst tmp; + loadUB_indirect_ac(tmp, mem); + convB2I_reg_2(dst, tmp); + %} +%} + +instruct loadUB_indOffset16(iRegIdst dst, indOffset16 mem) %{ + // match-rule, false predicate + match(Set dst (LoadB mem)); + predicate(false); + + format %{ "LBZ $dst, $mem" %} + size(4); + ins_encode( enc_lbz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +instruct loadUB_indOffset16_ac(iRegIdst dst, indOffset16 mem) %{ + // match-rule, false predicate + match(Set dst (LoadB mem)); + predicate(false); + + format %{ "LBZ $dst, $mem\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lbz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Byte (8bit signed). LoadB = LoadUB + ConvUB2B. +instruct loadB_indOffset16_Ex(iRegIdst dst, indOffset16 mem) %{ + match(Set dst (LoadB mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + expand %{ + iRegIdst tmp; + loadUB_indOffset16(tmp, mem); + convB2I_reg_2(dst, tmp); + %} +%} + +instruct loadB_indOffset16_ac_Ex(iRegIdst dst, indOffset16 mem) %{ + match(Set dst (LoadB mem)); + ins_cost(3*MEMORY_REF_COST + DEFAULT_COST); + + expand %{ + iRegIdst tmp; + loadUB_indOffset16_ac(tmp, mem); + convB2I_reg_2(dst, tmp); + %} +%} + +// Load Unsigned Byte (8bit UNsigned) into an int reg. +instruct loadUB(iRegIdst dst, memory mem) %{ + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + match(Set dst (LoadUB mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LBZ $dst, $mem \t// byte, zero-extend to int" %} + size(4); + ins_encode( enc_lbz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Unsigned Byte (8bit UNsigned) acquire. +instruct loadUB_ac(iRegIdst dst, memory mem) %{ + match(Set dst (LoadUB mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LBZ $dst, $mem \t// byte, zero-extend to int, acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lbz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Unsigned Byte (8bit UNsigned) into a Long Register. +instruct loadUB2L(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadUB mem))); + predicate(_kids[0]->_leaf->as_Load()->is_unordered() || followed_by_acquire(_kids[0]->_leaf)); + ins_cost(MEMORY_REF_COST); + + format %{ "LBZ $dst, $mem \t// byte, zero-extend to long" %} + size(4); + ins_encode( enc_lbz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +instruct loadUB2L_ac(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadUB mem))); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LBZ $dst, $mem \t// byte, zero-extend to long, acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lbz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Short (16bit signed) +instruct loadS(iRegIdst dst, memory mem) %{ + match(Set dst (LoadS mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Short (16bit signed) acquire. +instruct loadS_ac(iRegIdst dst, memory mem) %{ + match(Set dst (LoadS mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LHA $dst, $mem\t acquire\n\t" + "TWI $dst\n\t" + "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); + __ isync(); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Char (16bit unsigned) +instruct loadUS(iRegIdst dst, memory mem) %{ + match(Set dst (LoadUS mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LHZ $dst, $mem" %} + size(4); + ins_encode( enc_lhz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Char (16bit unsigned) acquire. +instruct loadUS_ac(iRegIdst dst, memory mem) %{ + match(Set dst (LoadUS mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LHZ $dst, $mem \t// acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lhz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register. +instruct loadUS2L(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadUS mem))); + predicate(_kids[0]->_leaf->as_Load()->is_unordered() || followed_by_acquire(_kids[0]->_leaf)); + ins_cost(MEMORY_REF_COST); + + format %{ "LHZ $dst, $mem \t// short, zero-extend to long" %} + size(4); + ins_encode( enc_lhz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register acquire. +instruct loadUS2L_ac(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadUS mem))); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LHZ $dst, $mem \t// short, zero-extend to long, acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lhz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Integer. +instruct loadI(iRegIdst dst, memory mem) %{ + match(Set dst (LoadI mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Integer acquire. +instruct loadI_ac(iRegIdst dst, memory mem) %{ + match(Set dst (LoadI mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// load acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lwz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Match loading integer and casting it to unsigned int in +// long register. +// LoadI + ConvI2L + AndL 0xffffffff. +instruct loadUI2L(iRegLdst dst, memory mem, immL_32bits mask) %{ + match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); + predicate(_kids[0]->_kids[0]->_leaf->as_Load()->is_unordered()); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// zero-extend to long" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Match loading integer and casting it to long. +instruct loadI2L(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadI mem))); + predicate(_kids[0]->_leaf->as_Load()->is_unordered()); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Match loading integer and casting it to long - acquire. +instruct loadI2L_ac(iRegLdst dst, memory mem) %{ + match(Set dst (ConvI2L (LoadI mem))); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LWA $dst, $mem \t// loadI2L acquire" + "TWI $dst\n\t" + "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); + __ isync(); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Long - aligned +instruct loadL(iRegLdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadL mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// long" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Long - aligned acquire. +instruct loadL_ac(iRegLdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadL mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// long acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_ld_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Long - UNaligned +instruct loadL_unaligned(iRegLdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadL_unaligned mem)); + // predicate(...) // Unaligned_ac is not needed (and wouldn't make sense). + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// unaligned long" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load nodes for superwords + +// Load Aligned Packed Byte +instruct loadV8(iRegLdst dst, memoryAlg4 mem) %{ + predicate(n->as_LoadVector()->memory_size() == 8); + match(Set dst (LoadVector mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// load 8-byte Vector" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Range, range = array length (=jint) +instruct loadRange(iRegIdst dst, memory mem) %{ + match(Set dst (LoadRange mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// range" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Compressed Pointer +instruct loadN(iRegNdst dst, memory mem) %{ + match(Set dst (LoadN mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// load compressed ptr" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Compressed Pointer acquire. +instruct loadN_ac(iRegNdst dst, memory mem) %{ + match(Set dst (LoadN mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// load acquire compressed ptr\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_lwz_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Compressed Pointer and decode it if narrow_oop_shift == 0. +instruct loadN2P_unscaled(iRegPdst dst, memory mem) %{ + match(Set dst (DecodeN (LoadN mem))); + predicate(_kids[0]->_leaf->as_Load()->is_unordered() && Universe::narrow_oop_shift() == 0); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// DecodeN (unscaled)" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Pointer +instruct loadP(iRegPdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadP mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// ptr" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Pointer acquire. +instruct loadP_ac(iRegPdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadP mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// ptr acquire\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_ld_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// LoadP + CastP2L +instruct loadP2X(iRegLdst dst, memoryAlg4 mem) %{ + match(Set dst (CastP2X (LoadP mem))); + predicate(_kids[0]->_leaf->as_Load()->is_unordered()); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// ptr + p2x" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load compressed klass pointer. +instruct loadNKlass(iRegNdst dst, memory mem) %{ + match(Set dst (LoadNKlass mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $mem \t// compressed klass ptr" %} + size(4); + ins_encode( enc_lwz(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +//// Load compressed klass and decode it if narrow_klass_shift == 0. +//// TODO: will narrow_klass_shift ever be 0? +//instruct decodeNKlass2Klass(iRegPdst dst, memory mem) %{ +// match(Set dst (DecodeNKlass (LoadNKlass mem))); +// predicate(false /* TODO: PPC port Universe::narrow_klass_shift() == 0*); +// ins_cost(MEMORY_REF_COST); +// +// format %{ "LWZ $dst, $mem \t// DecodeNKlass (unscaled)" %} +// size(4); +// ins_encode( enc_lwz(dst, mem) ); +// ins_pipe(pipe_class_memory); +//%} + +// Load Klass Pointer +instruct loadKlass(iRegPdst dst, memoryAlg4 mem) %{ + match(Set dst (LoadKlass mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// klass ptr" %} + size(4); + ins_encode( enc_ld(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Float +instruct loadF(regF dst, memory mem) %{ + match(Set dst (LoadF mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Float acquire. +instruct loadF_ac(regF dst, memory mem) %{ + match(Set dst (LoadF mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LFS $dst, $mem \t// acquire\n\t" + "FCMPU cr0, $dst, $dst\n\t" + "BNE cr0, next\n" + "next:\n\t" + "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); + __ fcmpu(CCR0, $dst$$FloatRegister, $dst$$FloatRegister); + __ bne(CCR0, next); + __ bind(next); + __ isync(); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Double - aligned +instruct loadD(regD dst, memory mem) %{ + match(Set dst (LoadD mem)); + predicate(n->as_Load()->is_unordered() || followed_by_acquire(n)); + ins_cost(MEMORY_REF_COST); + + format %{ "LFD $dst, $mem" %} + size(4); + ins_encode( enc_lfd(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Load Double - aligned acquire. +instruct loadD_ac(regD dst, memory mem) %{ + match(Set dst (LoadD mem)); + ins_cost(3*MEMORY_REF_COST); + + format %{ "LFD $dst, $mem \t// acquire\n\t" + "FCMPU cr0, $dst, $dst\n\t" + "BNE cr0, next\n" + "next:\n\t" + "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); + __ fcmpu(CCR0, $dst$$FloatRegister, $dst$$FloatRegister); + __ bne(CCR0, next); + __ bind(next); + __ isync(); + %} + ins_pipe(pipe_class_memory); +%} + +// Load Double - UNaligned +instruct loadD_unaligned(regD dst, memory mem) %{ + match(Set dst (LoadD_unaligned mem)); + // predicate(...) // Unaligned_ac is not needed (and wouldn't make sense). + ins_cost(MEMORY_REF_COST); + + format %{ "LFD $dst, $mem" %} + size(4); + ins_encode( enc_lfd(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +//----------Constants-------------------------------------------------------- + +// Load MachConstantTableBase: add hi offset to global toc. +// TODO: Handle hidden register r29 in bundler! +instruct loadToc_hi(iRegLdst dst) %{ + effect(DEF dst); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Load MachConstantTableBase: add lo offset to global toc. +instruct loadToc_lo(iRegLdst dst, iRegLdst src) %{ + effect(DEF dst, USE src); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Load 16-bit integer constant 0xssss???? +instruct loadConI16(iRegIdst dst, immI16 src) %{ + match(Set dst 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); +%} + +// Load integer constant 0x????0000 +instruct loadConIhi16(iRegIdst dst, immIhi16 src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST); + + 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))); + %} + ins_pipe(pipe_class_default); +%} + +// Part 2 of loading 32 bit constant: hi16 is is src1 (properly shifted +// and sign extended), this adds the low 16 bits. +instruct loadConI32_lo16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +instruct loadConI_Ex(iRegIdst dst, immI src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST*2); + + expand %{ + // Would like to use $src$$constant. + immI16 srcLo %{ _opnds[1]->constant() %} + // srcHi can be 0000 if srcLo sign-extends to a negative number. + immIhi16 srcHi %{ _opnds[1]->constant() %} + iRegIdst tmpI; + loadConIhi16(tmpI, srcHi); + loadConI32_lo16(dst, tmpI, srcLo); + %} +%} + +// No constant pool entries required. +instruct loadConL16(iRegLdst dst, immL16 src) %{ + match(Set dst 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); +%} + +// Load long constant 0xssssssss????0000 +instruct loadConL32hi16(iRegLdst dst, immL32hi16 src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST); + + 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); +%} + +// To load a 32 bit constant: merge lower 16 bits into already loaded +// high 16 bits. +instruct loadConL32_lo16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Load 32-bit long constant +instruct loadConL32_Ex(iRegLdst dst, immL32 src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST*2); + + expand %{ + // Would like to use $src$$constant. + immL16 srcLo %{ _opnds[1]->constant() /*& 0x0000FFFFL */%} + // srcHi can be 0000 if srcLo sign-extends to a negative number. + immL32hi16 srcHi %{ _opnds[1]->constant() /*& 0xFFFF0000L */%} + iRegLdst tmpL; + loadConL32hi16(tmpL, srcHi); + loadConL32_lo16(dst, tmpL, srcLo); + %} +%} + +// Load long constant 0x????000000000000. +instruct loadConLhighest16_Ex(iRegLdst dst, immLhighest16 src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST); + + expand %{ + immL32hi16 srcHi %{ _opnds[1]->constant() >> 32 /*& 0xFFFF0000L */%} + immI shift32 %{ 32 %} + iRegLdst tmpL; + loadConL32hi16(tmpL, srcHi); + lshiftL_regL_immI(dst, tmpL, shift32); + %} +%} + +// Expand node for constant pool load: small offset. +instruct loadConL(iRegLdst dst, immL src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + ins_cost(MEMORY_REF_COST); + + ins_num_consts(1); + // Needed so that CallDynamicJavaDirect can compute the address of this + // instruction for relocation. + ins_field_cbuf_insts_offset(int); + + format %{ "LD $dst, offset, $toc \t// load long $src from TOC" %} + size(4); + ins_encode( enc_load_long_constL(dst, src, toc) ); + ins_pipe(pipe_class_memory); +%} + +// Expand node for constant pool load: large offset. +instruct loadConL_hi(iRegLdst dst, immL src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + predicate(false); + + ins_num_consts(1); + ins_field_const_toc_offset(int); + // Needed so that CallDynamicJavaDirect can compute the address of this + // instruction for relocation. + ins_field_cbuf_insts_offset(int); + + format %{ "ADDIS $dst, $toc, offset \t// load long $src from TOC (hi)" %} + size(4); + ins_encode( enc_load_long_constL_hi(dst, toc, src) ); + ins_pipe(pipe_class_default); +%} + +// Expand node for constant pool load: large offset. +// No constant pool entries required. +instruct loadConL_lo(iRegLdst dst, immL src, iRegLdst base) %{ + effect(DEF dst, USE src, USE base); + predicate(false); + + ins_field_const_toc_offset_hi_node(loadConL_hiNode*); + + 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->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; + __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Load long constant from constant table. Expand in case of +// offset > 16 bit is needed. +// Adlc adds toc node MachConstantTableBase. +instruct loadConL_Ex(iRegLdst dst, immL src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, offset, $constanttablebase\t// load long $src from table, postalloc expanded" %} + // We can not inline the enc_class for the expand as that does not support constanttablebase. + postalloc_expand( postalloc_expand_load_long_constant(dst, src, constanttablebase) ); +%} + +// Load NULL as compressed oop. +instruct loadConN0(iRegNdst dst, immN_0 src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Load hi part of compressed oop constant. +instruct loadConN_hi(iRegNdst dst, immN src) %{ + effect(DEF dst, USE src); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Add lo part of compressed oop constant to already loaded hi part. +instruct loadConN_lo(iRegNdst dst, iRegNsrc src1, immN src2) %{ + effect(DEF dst, USE src1, USE src2); + ins_cost(DEFAULT_COST); + + 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); + __ relocate(rspec, 1); + __ ori($dst$$Register, $src1$$Register, $src2$$constant & 0xffff); + %} + ins_pipe(pipe_class_default); +%} + +// Needed to postalloc expand loadConN: ConN is loaded as ConI +// leaving the upper 32 bits with sign-extension bits. +// This clears these bits: dst = src & 0xFFFFFFFF. +// TODO: Eventually call this maskN_regN_FFFFFFFF. +instruct clearMs32b(iRegNdst dst, iRegNsrc src) %{ + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Loading ConN must be postalloc expanded so that edges between +// the nodes are safe. They may not interfere with a safepoint. +// GL TODO: This needs three instructions: better put this into the constant pool. +instruct loadConN_Ex(iRegNdst dst, immN src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST*2); + + format %{ "LoadN $dst, $src \t// postalloc expanded" %} // mask + postalloc_expand %{ + MachNode *m1 = new (C) loadConN_hiNode(); + MachNode *m2 = new (C) loadConN_loNode(); + MachNode *m3 = new (C) clearMs32bNode(); + m1->add_req(NULL); + m2->add_req(NULL, m1); + m3->add_req(NULL, m2); + m1->_opnds[0] = op_dst; + m1->_opnds[1] = op_src; + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_dst; + m2->_opnds[2] = op_src; + m3->_opnds[0] = op_dst; + m3->_opnds[1] = op_dst; + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(m3->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m1); + nodes->push(m2); + nodes->push(m3); + %} +%} + +instruct loadConNKlass_hi(iRegNdst dst, immNKlass src) %{ + effect(DEF dst, USE src); + ins_cost(DEFAULT_COST); + + format %{ "LIS $dst, $src \t// narrow oop hi" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addis); + intptr_t Csrc = Klass::encode_klass((Klass *)$src$$constant); + __ lis($dst$$Register, (int)(short)((Csrc >> 16) & 0xffff)); + %} + ins_pipe(pipe_class_default); +%} + +// This needs a match rule so that build_oop_map knows this is +// not a narrow oop. +instruct loadConNKlass_lo(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ + match(Set dst src1); + effect(TEMP src2); + ins_cost(DEFAULT_COST); + + format %{ "ADDI $dst, $src1, $src2 \t// narrow oop lo" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + intptr_t Csrc = Klass::encode_klass((Klass *)$src1$$constant); + assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = __ oop_recorder()->find_index((Klass *)$src1$$constant); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + + __ relocate(rspec, 1); + __ ori($dst$$Register, $src2$$Register, Csrc & 0xffff); + %} + ins_pipe(pipe_class_default); +%} + +// Loading ConNKlass must be postalloc expanded so that edges between +// the nodes are safe. They may not interfere with a safepoint. +instruct loadConNKlass_Ex(iRegNdst dst, immNKlass src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST*2); + + format %{ "LoadN $dst, $src \t// postalloc expanded" %} // mask + postalloc_expand %{ + // Load high bits into register. Sign extended. + MachNode *m1 = new (C) loadConNKlass_hiNode(); + m1->add_req(NULL); + m1->_opnds[0] = op_dst; + m1->_opnds[1] = op_src; + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m1); + + MachNode *m2 = m1; + if (!Assembler::is_uimm((jlong)Klass::encode_klass((Klass *)op_src->constant()), 31)) { + // Value might be 1-extended. Mask out these bits. + m2 = new (C) clearMs32bNode(); + m2->add_req(NULL, m1); + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_dst; + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m2); + } + + MachNode *m3 = new (C) loadConNKlass_loNode(); + m3->add_req(NULL, m2); + m3->_opnds[0] = op_dst; + m3->_opnds[1] = op_src; + m3->_opnds[2] = op_dst; + ra_->set_pair(m3->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + nodes->push(m3); + %} +%} + +// 0x1 is used in object initialization (initial object header). +// No constant pool entries required. +instruct loadConP0or1(iRegPdst dst, immP_0or1 src) %{ + match(Set dst 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); +%} + +// Expand node for constant pool load: small offset. +// The match rule is needed to generate the correct bottom_type(), +// however this node should never match. The use of predicate is not +// possible since ADLC forbids predicates for chain rules. The higher +// costs do not prevent matching in this case. For that reason the +// operand immP_NM with predicate(false) is used. +instruct loadConP(iRegPdst dst, immP_NM src, iRegLdst toc) %{ + match(Set dst src); + effect(TEMP toc); + + ins_num_consts(1); + + format %{ "LD $dst, offset, $toc \t// load ptr $src from TOC" %} + size(4); + ins_encode( enc_load_long_constP(dst, src, toc) ); + ins_pipe(pipe_class_memory); +%} + +// Expand node for constant pool load: large offset. +instruct loadConP_hi(iRegPdst dst, immP_NM src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + predicate(false); + + ins_num_consts(1); + ins_field_const_toc_offset(int); + + format %{ "ADDIS $dst, $toc, offset \t// load ptr $src from TOC (hi)" %} + size(4); + ins_encode( enc_load_long_constP_hi(dst, src, toc) ); + ins_pipe(pipe_class_default); +%} + +// Expand node for constant pool load: large offset. +instruct loadConP_lo(iRegPdst dst, immP_NM src, iRegLdst base) %{ + match(Set dst src); + effect(TEMP base); + + ins_field_const_toc_offset_hi_node(loadConP_hiNode*); + + 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->in_scratch_emit_size() ? 0 : MacroAssembler::largeoffset_si16_si16_lo(_const_toc_offset_hi_node->_const_toc_offset); + __ ld($dst$$Register, offset, $base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Load pointer constant from constant table. Expand in case an +// offset > 16 bit is needed. +// Adlc adds toc node MachConstantTableBase. +instruct loadConP_Ex(iRegPdst dst, immP src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + // This rule does not use "expand" because then + // the result type is not known to be an Oop. An ADLC + // enhancement will be needed to make that work - not worth it! + + // If this instruction rematerializes, it prolongs the live range + // of the toc node, causing illegal graphs. + // assert(edge_from_to(_reg_node[reg_lo],def)) fails in verify_good_schedule(). + ins_cannot_rematerialize(true); + + format %{ "LD $dst, offset, $constanttablebase \t// load ptr $src from table, postalloc expanded" %} + postalloc_expand( postalloc_expand_load_ptr_constant(dst, src, constanttablebase) ); +%} + +// Expand node for constant pool load: small offset. +instruct loadConF(regF dst, immF src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + ins_cost(MEMORY_REF_COST); + + ins_num_consts(1); + + 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); + __ lfs($dst$$FloatRegister, __ offset_to_method_toc(float_address), $toc$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Expand node for constant pool load: large offset. +instruct loadConFComp(regF dst, immF src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + ins_cost(MEMORY_REF_COST); + + ins_num_consts(1); + + format %{ "ADDIS $toc, $toc, offset_hi\n\t" + "LFS $dst, offset_lo, $toc \t// load float $src from TOC (hi/lo)\n\t" + "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); + int offset = __ offset_to_method_toc(float_address); + int hi = (offset + (1<<15))>>16; + int lo = offset - hi * (1<<16); + + __ addis(Rtoc, Rtoc, hi); + __ lfs(Rdst, lo, Rtoc); + __ addis(Rtoc, Rtoc, -hi); + %} + ins_pipe(pipe_class_memory); +%} + +// Adlc adds toc node MachConstantTableBase. +instruct loadConF_Ex(regF dst, immF src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + // See loadConP. + ins_cannot_rematerialize(true); + + format %{ "LFS $dst, offset, $constanttablebase \t// load $src from table, postalloc expanded" %} + postalloc_expand( postalloc_expand_load_float_constant(dst, src, constanttablebase) ); +%} + +// Expand node for constant pool load: small offset. +instruct loadConD(regD dst, immD src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + ins_cost(MEMORY_REF_COST); + + ins_num_consts(1); + + format %{ "LFD $dst, offset, $toc \t// load double $src from TOC" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lfd); + int offset = __ offset_to_method_toc(__ double_constant($src$$constant)); + __ lfd($dst$$FloatRegister, offset, $toc$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Expand node for constant pool load: large offset. +instruct loadConDComp(regD dst, immD src, iRegLdst toc) %{ + effect(DEF dst, USE src, USE toc); + ins_cost(MEMORY_REF_COST); + + ins_num_consts(1); + + format %{ "ADDIS $toc, $toc, offset_hi\n\t" + "LFD $dst, offset_lo, $toc \t// load double $src from TOC (hi/lo)\n\t" + "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); + int offset = __ offset_to_method_toc(float_address); + int hi = (offset + (1<<15))>>16; + int lo = offset - hi * (1<<16); + + __ addis(Rtoc, Rtoc, hi); + __ lfd(Rdst, lo, Rtoc); + __ addis(Rtoc, Rtoc, -hi); + %} + ins_pipe(pipe_class_memory); +%} + +// Adlc adds toc node MachConstantTableBase. +instruct loadConD_Ex(regD dst, immD src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + // See loadConP. + ins_cannot_rematerialize(true); + + format %{ "ConD $dst, offset, $constanttablebase \t// load $src from table, postalloc expanded" %} + postalloc_expand( postalloc_expand_load_double_constant(dst, src, constanttablebase) ); +%} + +// Prefetch instructions. +// Must be safe to execute with invalid address (cannot fault). + +instruct prefetchr(indirectMemory mem, iRegLsrc src) %{ + match(PrefetchRead (AddP mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "PREFETCH $mem, 0, $src \t// Prefetch read-many" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_dcbt); + __ dcbt($src$$Register, $mem$$base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +instruct prefetchr_no_offset(indirectMemory mem) %{ + match(PrefetchRead mem); + ins_cost(MEMORY_REF_COST); + + format %{ "PREFETCH $mem" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_dcbt); + __ dcbt($mem$$base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +instruct prefetchw(indirectMemory mem, iRegLsrc src) %{ + match(PrefetchWrite (AddP mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "PREFETCH $mem, 2, $src \t// Prefetch write-many (and read)" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); + __ dcbtst($src$$Register, $mem$$base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +instruct prefetchw_no_offset(indirectMemory mem) %{ + match(PrefetchWrite mem); + ins_cost(MEMORY_REF_COST); + + format %{ "PREFETCH $mem" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_dcbtst); + __ dcbtst($mem$$base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Special prefetch versions which use the dcbz instruction. +instruct prefetch_alloc_zero(indirectMemory mem, iRegLsrc src) %{ + match(PrefetchAllocation (AddP mem src)); + predicate(AllocatePrefetchStyle == 3); + ins_cost(MEMORY_REF_COST); + + 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); +%} + +instruct prefetch_alloc_zero_no_offset(indirectMemory mem) %{ + match(PrefetchAllocation mem); + predicate(AllocatePrefetchStyle == 3); + ins_cost(MEMORY_REF_COST); + + 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); +%} + +instruct prefetch_alloc(indirectMemory mem, iRegLsrc src) %{ + match(PrefetchAllocation (AddP mem src)); + predicate(AllocatePrefetchStyle != 3); + ins_cost(MEMORY_REF_COST); + + 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); +%} + +instruct prefetch_alloc_no_offset(indirectMemory mem) %{ + match(PrefetchAllocation mem); + predicate(AllocatePrefetchStyle != 3); + ins_cost(MEMORY_REF_COST); + + 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); +%} + +//----------Store Instructions------------------------------------------------- + +// Store Byte +instruct storeB(memory mem, iRegIsrc src) %{ + match(Set mem (StoreB mem src)); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Store Char/Short +instruct storeC(memory mem, iRegIsrc src) %{ + match(Set mem (StoreC mem src)); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Store Integer +instruct storeI(memory mem, iRegIsrc src) %{ + match(Set mem (StoreI mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STW $src, $mem" %} + size(4); + ins_encode( enc_stw(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +// ConvL2I + StoreI. +instruct storeI_convL2I(memory mem, iRegLsrc src) %{ + match(Set mem (StoreI mem (ConvL2I src))); + ins_cost(MEMORY_REF_COST); + + format %{ "STW l2i($src), $mem" %} + size(4); + ins_encode( enc_stw(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Store Long +instruct storeL(memoryAlg4 mem, iRegLsrc src) %{ + match(Set mem (StoreL mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STD $src, $mem \t// long" %} + size(4); + ins_encode( enc_std(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Store super word nodes. + +// Store Aligned Packed Byte long register to memory +instruct storeA8B(memoryAlg4 mem, iRegLsrc src) %{ + predicate(n->as_StoreVector()->memory_size() == 8); + match(Set mem (StoreVector mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STD $mem, $src \t// packed8B" %} + size(4); + ins_encode( enc_std(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Store Compressed Oop +instruct storeN(memory dst, iRegN_P2N src) %{ + match(Set dst (StoreN dst src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STW $src, $dst \t// compressed oop" %} + size(4); + ins_encode( enc_stw(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +// Store Compressed KLass +instruct storeNKlass(memory dst, iRegN_P2N src) %{ + match(Set dst (StoreNKlass dst src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STW $src, $dst \t// compressed klass" %} + size(4); + ins_encode( enc_stw(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +// Store Pointer +instruct storeP(memoryAlg4 dst, iRegPsrc src) %{ + match(Set dst (StoreP dst src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STD $src, $dst \t// ptr" %} + size(4); + ins_encode( enc_std(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +// Store Float +instruct storeF(memory mem, regF src) %{ + match(Set mem (StoreF mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STFS $src, $mem" %} + size(4); + ins_encode( enc_stfs(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +// Store Double +instruct storeD(memory mem, regD src) %{ + match(Set mem (StoreD mem src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STFD $src, $mem" %} + size(4); + ins_encode( enc_stfd(src, mem) ); + ins_pipe(pipe_class_memory); +%} + +//----------Store Instructions With Zeros-------------------------------------- + +// Card-mark for CMS garbage collection. +// This cardmark does an optimization so that it must not always +// do a releasing store. For this, it gets the address of +// CMSCollectorCardTableModRefBSExt::_requires_release as input. +// (Using releaseFieldAddr in the match rule is a hack.) +instruct storeCM_CMS(memory mem, iRegLdst releaseFieldAddr) %{ + match(Set mem (StoreCM mem releaseFieldAddr)); + predicate(false); + ins_cost(MEMORY_REF_COST); + + // See loadConP. + ins_cannot_rematerialize(true); + + format %{ "STB #0, $mem \t// CMS card-mark byte (must be 0!), checking requires_release in [$releaseFieldAddr]" %} + ins_encode( enc_cms_card_mark(mem, releaseFieldAddr) ); + ins_pipe(pipe_class_memory); +%} + +// Card-mark for CMS garbage collection. +// This cardmark does an optimization so that it must not always +// do a releasing store. For this, it needs the constant address of +// CMSCollectorCardTableModRefBSExt::_requires_release. +// This constant address is split off here by expand so we can use +// adlc / matcher functionality to load it from the constant section. +instruct storeCM_CMS_ExEx(memory mem, immI_0 zero) %{ + match(Set mem (StoreCM mem zero)); + predicate(UseConcMarkSweepGC); + + expand %{ + immL baseImm %{ 0 /* TODO: PPC port (jlong)CMSCollectorCardTableModRefBSExt::requires_release_address() */ %} + iRegLdst releaseFieldAddress; + loadConL_Ex(releaseFieldAddress, baseImm); + storeCM_CMS(mem, releaseFieldAddress); + %} +%} + +instruct storeCM_G1(memory mem, immI_0 zero) %{ + match(Set mem (StoreCM mem zero)); + predicate(UseG1GC); + ins_cost(MEMORY_REF_COST); + + ins_cannot_rematerialize(true); + + 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"); + __ stb(R0, $mem$$disp, $mem$$base$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +// Convert oop pointer into compressed form. + +// Nodes for postalloc expand. + +// Shift node for expand. +instruct encodeP_shift(iRegNdst dst, iRegNsrc src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodeP src)); + predicate(false); + + format %{ "SRDI $dst, $src, 3 \t// encode" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ srdi($dst$$Register, $src$$Register, Universe::narrow_oop_shift() & 0x3f); + %} + ins_pipe(pipe_class_default); +%} + +// Add node for expand. +instruct encodeP_sub(iRegPdst dst, iRegPdst src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodeP src)); + predicate(false); + + format %{ "SUB $dst, $src, oop_base \t// encode" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_subf); + __ subf($dst$$Register, R30, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Conditional sub base. +instruct cond_sub_base(iRegNdst dst, flagsReg crx, iRegPsrc src1) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodeP (Binary crx src1))); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + format %{ "BEQ $crx, done\n\t" + "SUB $dst, $src1, R30 \t// encode: subtract base if != NULL\n" + "done:" %} + size(false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + Label done; + __ beq($crx$$CondRegister, done); + __ subf($dst$$Register, R30, $src1$$Register); + // TODO PPC port __ endgroup_if_needed(_size == 12); + __ bind(done); + %} + ins_pipe(pipe_class_default); +%} + +// Power 7 can use isel instruction +instruct cond_set_0_oop(iRegNdst dst, flagsReg crx, iRegPsrc src1) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodeP (Binary crx src1))); + predicate(false); + + format %{ "CMOVE $dst, $crx eq, 0, $src1 \t// encode: preserve 0" %} + 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); +%} + +// base != 0 +// 32G aligned narrow oop base. +instruct encodeP_32GAligned(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodeP src)); + predicate(false /* TODO: PPC port Universe::narrow_oop_base_disjoint()*/); + + format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ rldicl($dst$$Register, $src$$Register, 64-Universe::narrow_oop_shift(), 32); + %} + ins_pipe(pipe_class_default); +%} + +// shift != 0, base != 0 +instruct encodeP_Ex(iRegNdst dst, flagsReg crx, iRegPsrc src) %{ + match(Set dst (EncodeP src)); + effect(TEMP crx); + predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull && + Universe::narrow_oop_shift() != 0 && + true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/); + + format %{ "EncodeP $dst, $crx, $src \t// postalloc expanded" %} + postalloc_expand( postalloc_expand_encode_oop(dst, src, crx)); +%} + +// shift != 0, base != 0 +instruct encodeP_not_null_Ex(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodeP src)); + predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull && + Universe::narrow_oop_shift() != 0 && + true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/); + + format %{ "EncodeP $dst, $src\t// $src != Null, postalloc expanded" %} + postalloc_expand( postalloc_expand_encode_oop_not_null(dst, src) ); +%} + +// shift != 0, base == 0 +// TODO: This is the same as encodeP_shift. Merge! +instruct encodeP_not_null_base_null(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodeP src)); + predicate(Universe::narrow_oop_shift() != 0 && + Universe::narrow_oop_base() ==0); + + format %{ "SRDI $dst, $src, #3 \t// encodeP, $src != NULL" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ srdi($dst$$Register, $src$$Register, Universe::narrow_oop_shift() & 0x3f); + %} + ins_pipe(pipe_class_default); +%} + +// Compressed OOPs with narrow_oop_shift == 0. +// shift == 0, base == 0 +instruct encodeP_narrow_oop_shift_0(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodeP src)); + predicate(Universe::narrow_oop_shift() == 0); + + 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); +%} + +// Decode nodes. + +// Shift node for expand. +instruct decodeN_shift(iRegPdst dst, iRegPsrc src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (DecodeN src)); + predicate(false); + + format %{ "SLDI $dst, $src, #3 \t// DecodeN" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); + __ sldi($dst$$Register, $src$$Register, Universe::narrow_oop_shift()); + %} + ins_pipe(pipe_class_default); +%} + +// Add node for expand. +instruct decodeN_add(iRegPdst dst, iRegPdst src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (DecodeN src)); + predicate(false); + + format %{ "ADD $dst, $src, R30 \t// DecodeN, add oop base" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_add); + __ add($dst$$Register, $src$$Register, R30); + %} + ins_pipe(pipe_class_default); +%} + +// conditianal add base for expand +instruct cond_add_base(iRegPdst dst, flagsReg crx, iRegPsrc src1) %{ + // The match rule is needed to make it a 'MachTypeNode'! + // NOTICE that the rule is nonsense - we just have to make sure that: + // - _matrule->_rChild->_opType == "DecodeN" (see InstructForm::captures_bottom_type() in formssel.cpp) + // - we have to match 'crx' to avoid an "illegal USE of non-input: flagsReg crx" error in ADLC. + match(Set dst (DecodeN (Binary crx src1))); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + format %{ "BEQ $crx, done\n\t" + "ADD $dst, $src1, R30 \t// DecodeN: add oop base if $src1 != NULL\n" + "done:" %} + size(false /* TODO: PPC PORT (InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling()) */? 12 : 8); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + Label done; + __ beq($crx$$CondRegister, done); + __ add($dst$$Register, $src1$$Register, R30); + // TODO PPC port __ endgroup_if_needed(_size == 12); + __ bind(done); + %} + ins_pipe(pipe_class_default); +%} + +instruct cond_set_0_ptr(iRegPdst dst, flagsReg crx, iRegPsrc src1) %{ + // The match rule is needed to make it a 'MachTypeNode'! + // NOTICE that the rule is nonsense - we just have to make sure that: + // - _matrule->_rChild->_opType == "DecodeN" (see InstructForm::captures_bottom_type() in formssel.cpp) + // - we have to match 'crx' to avoid an "illegal USE of non-input: flagsReg crx" error in ADLC. + match(Set dst (DecodeN (Binary crx src1))); + predicate(false); + + format %{ "CMOVE $dst, $crx eq, 0, $src1 \t// decode: preserve 0" %} + 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); +%} + +// shift != 0, base != 0 +instruct decodeN_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{ + match(Set dst (DecodeN src)); + predicate((n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && + n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) && + Universe::narrow_oop_shift() != 0 && + Universe::narrow_oop_base() != 0); + effect(TEMP crx); + + format %{ "DecodeN $dst, $src \t// Kills $crx, postalloc expanded" %} + postalloc_expand( postalloc_expand_decode_oop(dst, src, crx) ); +%} + +// shift != 0, base == 0 +instruct decodeN_nullBase(iRegPdst dst, iRegNsrc src) %{ + match(Set dst (DecodeN src)); + predicate(Universe::narrow_oop_shift() != 0 && + Universe::narrow_oop_base() == 0); + + format %{ "SLDI $dst, $src, #3 \t// DecodeN (zerobased)" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); + __ sldi($dst$$Register, $src$$Register, Universe::narrow_oop_shift()); + %} + ins_pipe(pipe_class_default); +%} + +// src != 0, shift != 0, base != 0 +instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{ + match(Set dst (DecodeN src)); + predicate((n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || + n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) && + Universe::narrow_oop_shift() != 0 && + Universe::narrow_oop_base() != 0); + + format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %} + postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src)); +%} + +// Compressed OOPs with narrow_oop_shift == 0. +instruct decodeN_unscaled(iRegPdst dst, iRegNsrc src) %{ + match(Set dst (DecodeN src)); + predicate(Universe::narrow_oop_shift() == 0); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Convert compressed oop into int for vectors alignment masking. +instruct decodeN2I_unscaled(iRegIdst dst, iRegNsrc src) %{ + match(Set dst (ConvL2I (CastP2X (DecodeN src)))); + predicate(Universe::narrow_oop_shift() == 0); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Convert klass pointer into compressed form. + +// Nodes for postalloc expand. + +// Shift node for expand. +instruct encodePKlass_shift(iRegNdst dst, iRegNsrc src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodePKlass src)); + predicate(false); + + format %{ "SRDI $dst, $src, 3 \t// encode" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ srdi($dst$$Register, $src$$Register, Universe::narrow_klass_shift()); + %} + ins_pipe(pipe_class_default); +%} + +// Add node for expand. +instruct encodePKlass_sub_base(iRegPdst dst, iRegLsrc base, iRegPdst src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (EncodePKlass (Binary base src))); + predicate(false); + + 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); +%} + +// base != 0 +// 32G aligned narrow oop base. +instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodePKlass src)); + predicate(false /* TODO: PPC port Universe::narrow_klass_base_disjoint()*/); + + format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ rldicl($dst$$Register, $src$$Register, 64-Universe::narrow_oop_shift(), 32); + %} + ins_pipe(pipe_class_default); +%} + +// shift != 0, base != 0 +instruct encodePKlass_not_null_Ex(iRegNdst dst, iRegLsrc base, iRegPsrc src) %{ + match(Set dst (EncodePKlass (Binary base src))); + predicate(false); + + format %{ "EncodePKlass $dst, $src\t// $src != Null, postalloc expanded" %} + postalloc_expand %{ + encodePKlass_sub_baseNode *n1 = new (C) encodePKlass_sub_baseNode(); + n1->add_req(n_region, n_base, n_src); + n1->_opnds[0] = op_dst; + n1->_opnds[1] = op_base; + n1->_opnds[2] = op_src; + n1->_bottom_type = _bottom_type; + + encodePKlass_shiftNode *n2 = new (C) encodePKlass_shiftNode(); + n2->add_req(n_region, n1); + n2->_opnds[0] = op_dst; + n2->_opnds[1] = op_dst; + n2->_bottom_type = _bottom_type; + ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n1); + nodes->push(n2); + %} +%} + +// shift != 0, base != 0 +instruct encodePKlass_not_null_ExEx(iRegNdst dst, iRegPsrc src) %{ + match(Set dst (EncodePKlass src)); + //predicate(Universe::narrow_klass_shift() != 0 && + // true /* TODO: PPC port Universe::narrow_klass_base_overlaps()*/); + + //format %{ "EncodePKlass $dst, $src\t// $src != Null, postalloc expanded" %} + ins_cost(DEFAULT_COST*2); // Don't count constant. + expand %{ + immL baseImm %{ (jlong)(intptr_t)Universe::narrow_klass_base() %} + iRegLdst base; + loadConL_Ex(base, baseImm); + encodePKlass_not_null_Ex(dst, base, src); + %} +%} + +// Decode nodes. + +// Shift node for expand. +instruct decodeNKlass_shift(iRegPdst dst, iRegPsrc src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (DecodeNKlass src)); + predicate(false); + + format %{ "SLDI $dst, $src, #3 \t// DecodeNKlass" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicr); + __ sldi($dst$$Register, $src$$Register, Universe::narrow_klass_shift()); + %} + ins_pipe(pipe_class_default); +%} + +// Add node for expand. + +instruct decodeNKlass_add_base(iRegPdst dst, iRegLsrc base, iRegPdst src) %{ + // The match rule is needed to make it a 'MachTypeNode'! + match(Set dst (DecodeNKlass (Binary base src))); + predicate(false); + + 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); +%} + +// src != 0, shift != 0, base != 0 +instruct decodeNKlass_notNull_addBase_Ex(iRegPdst dst, iRegLsrc base, iRegNsrc src) %{ + match(Set dst (DecodeNKlass (Binary base src))); + //effect(kill src); // We need a register for the immediate result after shifting. + predicate(false); + + format %{ "DecodeNKlass $dst = $base + ($src << 3) \t// $src != NULL, postalloc expanded" %} + postalloc_expand %{ + decodeNKlass_add_baseNode *n1 = new (C) decodeNKlass_add_baseNode(); + n1->add_req(n_region, n_base, n_src); + n1->_opnds[0] = op_dst; + n1->_opnds[1] = op_base; + n1->_opnds[2] = op_src; + n1->_bottom_type = _bottom_type; + + decodeNKlass_shiftNode *n2 = new (C) decodeNKlass_shiftNode(); + n2->add_req(n_region, n2); + n2->_opnds[0] = op_dst; + n2->_opnds[1] = op_dst; + n2->_bottom_type = _bottom_type; + + ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); + + nodes->push(n1); + nodes->push(n2); + %} +%} + +// src != 0, shift != 0, base != 0 +instruct decodeNKlass_notNull_addBase_ExEx(iRegPdst dst, iRegNsrc src) %{ + match(Set dst (DecodeNKlass src)); + // predicate(Universe::narrow_klass_shift() != 0 && + // Universe::narrow_klass_base() != 0); + + //format %{ "DecodeNKlass $dst, $src \t// $src != NULL, expanded" %} + + ins_cost(DEFAULT_COST*2); // Don't count constant. + expand %{ + // We add first, then we shift. Like this, we can get along with one register less. + // But we have to load the base pre-shifted. + immL baseImm %{ (jlong)((intptr_t)Universe::narrow_klass_base() >> Universe::narrow_klass_shift()) %} + iRegLdst base; + loadConL_Ex(base, baseImm); + decodeNKlass_notNull_addBase_Ex(dst, base, src); + %} +%} + +//----------MemBar Instructions----------------------------------------------- +// Memory barrier flavors + +instruct membar_acquire() %{ + match(LoadFence); + ins_cost(4*MEMORY_REF_COST); + + format %{ "MEMBAR-acquire" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); + __ acquire(); + %} + ins_pipe(pipe_class_default); +%} + +instruct unnecessary_membar_acquire() %{ + match(MemBarAcquire); + ins_cost(0); + + format %{ " -- \t// redundant MEMBAR-acquire - empty" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct membar_acquire_lock() %{ + match(MemBarAcquireLock); + ins_cost(0); + + format %{ " -- \t// redundant MEMBAR-acquire - empty (acquire as part of CAS in prior FastLock)" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct membar_release() %{ + match(MemBarRelease); + match(StoreFence); + ins_cost(4*MEMORY_REF_COST); + + format %{ "MEMBAR-release" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); + __ release(); + %} + ins_pipe(pipe_class_default); +%} + +instruct membar_storestore() %{ + match(MemBarStoreStore); + ins_cost(4*MEMORY_REF_COST); + + format %{ "MEMBAR-store-store" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_lwsync); + __ membar(Assembler::StoreStore); + %} + ins_pipe(pipe_class_default); +%} + +instruct membar_release_lock() %{ + match(MemBarReleaseLock); + ins_cost(0); + + format %{ " -- \t// redundant MEMBAR-release - empty (release in FastUnlock)" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct membar_volatile() %{ + match(MemBarVolatile); + ins_cost(4*MEMORY_REF_COST); + + format %{ "MEMBAR-volatile" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_sync); + __ fence(); + %} + ins_pipe(pipe_class_default); +%} + +// This optimization is wrong on PPC. The following pattern is not supported: +// MemBarVolatile +// ^ ^ +// | | +// CtrlProj MemProj +// ^ ^ +// | | +// | Load +// | +// MemBarVolatile +// +// The first MemBarVolatile could get optimized out! According to +// Vladimir, this pattern can not occur on Oracle platforms. +// However, it does occur on PPC64 (because of membars in +// inline_unsafe_load_store). +// +// Add this node again if we found a good solution for inline_unsafe_load_store(). +// Don't forget to look at the implementation of post_store_load_barrier again, +// we did other fixes in that method. +//instruct unnecessary_membar_volatile() %{ +// match(MemBarVolatile); +// predicate(Matcher::post_store_load_barrier(n)); +// ins_cost(0); +// +// format %{ " -- \t// redundant MEMBAR-volatile - empty" %} +// size(0); +// ins_encode( /*empty*/ ); +// ins_pipe(pipe_class_default); +//%} + +instruct membar_CPUOrder() %{ + match(MemBarCPUOrder); + ins_cost(0); + + format %{ " -- \t// MEMBAR-CPUOrder - empty: PPC64 processors are self-consistent." %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +//----------Conditional Move--------------------------------------------------- + +// Cmove using isel. +instruct cmovI_reg_isel(cmpOp cmp, flagsReg crx, iRegIdst dst, iRegIsrc src) %{ + match(Set dst (CMoveI (Binary cmp crx) (Binary dst src))); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST); + + format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} + size(4); + 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); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmovI_reg(cmpOp cmp, flagsReg crx, iRegIdst dst, iRegIsrc src) %{ + match(Set dst (CMoveI (Binary cmp crx) (Binary dst src))); + predicate(!VM_Version::has_isel()); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovI_imm(cmpOp cmp, flagsReg crx, iRegIdst dst, immI16 src) %{ + match(Set dst (CMoveI (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +// Cmove using isel. +instruct cmovL_reg_isel(cmpOp cmp, flagsReg crx, iRegLdst dst, iRegLsrc src) %{ + match(Set dst (CMoveL (Binary cmp crx) (Binary dst src))); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST); + + format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} + size(4); + 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); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmovL_reg(cmpOp cmp, flagsReg crx, iRegLdst dst, iRegLsrc src) %{ + match(Set dst (CMoveL (Binary cmp crx) (Binary dst src))); + predicate(!VM_Version::has_isel()); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovL_imm(cmpOp cmp, flagsReg crx, iRegLdst dst, immL16 src) %{ + match(Set dst (CMoveL (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +// Cmove using isel. +instruct cmovN_reg_isel(cmpOp cmp, flagsReg crx, iRegNdst dst, iRegNsrc src) %{ + match(Set dst (CMoveN (Binary cmp crx) (Binary dst src))); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST); + + format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} + size(4); + 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); + %} + ins_pipe(pipe_class_default); +%} + +// Conditional move for RegN. Only cmov(reg, reg). +instruct cmovN_reg(cmpOp cmp, flagsReg crx, iRegNdst dst, iRegNsrc src) %{ + match(Set dst (CMoveN (Binary cmp crx) (Binary dst src))); + predicate(!VM_Version::has_isel()); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovN_imm(cmpOp cmp, flagsReg crx, iRegNdst dst, immN_0 src) %{ + match(Set dst (CMoveN (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +// Cmove using isel. +instruct cmovP_reg_isel(cmpOp cmp, flagsReg crx, iRegPdst dst, iRegPsrc src) %{ + match(Set dst (CMoveP (Binary cmp crx) (Binary dst src))); + predicate(VM_Version::has_isel()); + ins_cost(DEFAULT_COST); + + format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} + size(4); + 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); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmovP_reg(cmpOp cmp, flagsReg crx, iRegPdst dst, iRegP_N2P src) %{ + match(Set dst (CMoveP (Binary cmp crx) (Binary dst src))); + predicate(!VM_Version::has_isel()); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_reg(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovP_imm(cmpOp cmp, flagsReg crx, iRegPdst dst, immP_0 src) %{ + match(Set dst (CMoveP (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_imm(dst, crx, src, cmp) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovF_reg(cmpOp cmp, flagsReg crx, regF dst, regF src) %{ + match(Set dst (CMoveF (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +instruct cmovD_reg(cmpOp cmp, flagsReg crx, regD dst, regD src) %{ + match(Set dst (CMoveD (Binary cmp crx) (Binary dst src))); + ins_cost(DEFAULT_COST+BRANCH_COST); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +//----------Conditional_store-------------------------------------------------- +// Conditional-store of the updated heap-top. +// Used during allocation of the shared heap. +// Sets flags (EQ) on success. Implemented with a CASA on Sparc. + +// As compareAndSwapL, but return flag register instead of boolean value in +// int register. +// Used by sun/misc/AtomicLongCSImpl.java. +// Mem_ptr must be a memory operand, else this node does not get +// Flag_needs_anti_dependence_check set by adlc. If this is not set this node +// can be rematerialized which leads to errors. +instruct storeLConditional_regP_regL_regL(flagsReg crx, indirect mem_ptr, iRegLsrc oldVal, iRegLsrc newVal) %{ + match(Set crx (StoreLConditional mem_ptr (Binary oldVal newVal))); + 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::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), + noreg, NULL, true); + %} + ins_pipe(pipe_class_default); +%} + +// As compareAndSwapP, but return flag register instead of boolean value in +// int register. +// This instruction is matched if UseTLAB is off. +// Mem_ptr must be a memory operand, else this node does not get +// Flag_needs_anti_dependence_check set by adlc. If this is not set this node +// can be rematerialized which leads to errors. +instruct storePConditional_regP_regP_regP(flagsReg crx, indirect mem_ptr, iRegPsrc oldVal, iRegPsrc newVal) %{ + match(Set crx (StorePConditional mem_ptr (Binary oldVal newVal))); + 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::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(), + noreg, NULL, true); + %} + ins_pipe(pipe_class_default); +%} + +// Implement LoadPLocked. Must be ordered against changes of the memory location +// by storePConditional. +// Don't know whether this is ever used. +instruct loadPLocked(iRegPdst dst, memory mem) %{ + match(Set dst (LoadPLocked mem)); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $mem \t// loadPLocked\n\t" + "TWI $dst\n\t" + "ISYNC" %} + size(12); + ins_encode( enc_ld_ac(dst, mem) ); + ins_pipe(pipe_class_memory); +%} + +//----------Compare-And-Swap--------------------------------------------------- + +// CompareAndSwap{P,I,L} have more than one output, therefore "CmpI +// (CompareAndSwap ...)" or "If (CmpI (CompareAndSwap ..))" cannot be +// matched. + +instruct compareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2) %{ + match(Set res (CompareAndSwapI mem_ptr (Binary src1 src2))); + format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} + // Variable size: instruction count smaller if regs are disjoint. + 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::MemBarFenceAfter, MacroAssembler::cmpxchgx_hint_atomic_update(), + $res$$Register, true); + %} + ins_pipe(pipe_class_default); +%} + +instruct compareAndSwapN_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2) %{ + match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2))); + format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %} + // Variable size: instruction count smaller if regs are disjoint. + 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::MemBarFenceAfter, MacroAssembler::cmpxchgx_hint_atomic_update(), + $res$$Register, true); + %} + ins_pipe(pipe_class_default); +%} + +instruct compareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc src1, iRegLsrc src2) %{ + match(Set res (CompareAndSwapL mem_ptr (Binary src1 src2))); + format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool" %} + // Variable size: instruction count smaller if regs are disjoint. + 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::MemBarFenceAfter, MacroAssembler::cmpxchgx_hint_atomic_update(), + $res$$Register, NULL, true); + %} + ins_pipe(pipe_class_default); +%} + +instruct compareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2) %{ + match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2))); + format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %} + // Variable size: instruction count smaller if regs are disjoint. + 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::MemBarFenceAfter, MacroAssembler::cmpxchgx_hint_atomic_update(), + $res$$Register, NULL, true); + %} + ins_pipe(pipe_class_default); +%} + +instruct getAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ + match(Set res (GetAndAddI mem_ptr src)); + format %{ "GetAndAddI $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndAddI(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +instruct getAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ + match(Set res (GetAndAddL mem_ptr src)); + format %{ "GetAndAddL $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndAddL(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +instruct getAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{ + match(Set res (GetAndSetI mem_ptr src)); + format %{ "GetAndSetI $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndSetI(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +instruct getAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{ + match(Set res (GetAndSetL mem_ptr src)); + format %{ "GetAndSetL $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndSetL(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +instruct getAndSetP(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src) %{ + match(Set res (GetAndSetP mem_ptr src)); + format %{ "GetAndSetP $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndSetL(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +instruct getAndSetN(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src) %{ + match(Set res (GetAndSetN mem_ptr src)); + format %{ "GetAndSetN $res, $mem_ptr, $src" %} + // Variable size: instruction count smaller if regs are disjoint. + ins_encode( enc_GetAndSetI(res, mem_ptr, src) ); + ins_pipe(pipe_class_default); +%} + +//----------Arithmetic Instructions-------------------------------------------- +// Addition Instructions + +// PPC has no instruction setting overflow of 32-bit integer. +//instruct addExactI_rReg(rarg4RegI dst, rRegI src, flagsReg cr) %{ +// match(AddExactI dst src); +// effect(DEF cr); +// +// format %{ "ADD $dst, $dst, $src \t// addExact int, sets $cr" %} +// ins_encode( enc_add(dst, dst, src) ); +// ins_pipe(pipe_class_default); +//%} + +// Register Addition +instruct addI_reg_reg(iRegIdst dst, iRegIsrc_iRegL2Isrc src1, iRegIsrc_iRegL2Isrc src2) %{ + match(Set dst (AddI src1 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); +%} + +// Expand does not work with above instruct. (??) +instruct addI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule + effect(DEF dst, USE src1, USE 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); +%} + +instruct tree_addI_addI_addI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, iRegIsrc src3, iRegIsrc src4) %{ + match(Set dst (AddI (AddI (AddI src1 src2) src3) src4)); + ins_cost(DEFAULT_COST*3); + + expand %{ + // FIXME: we should do this in the ideal world. + iRegIdst tmp1; + iRegIdst tmp2; + addI_reg_reg(tmp1, src1, src2); + addI_reg_reg_2(tmp2, src3, src4); // Adlc complains about addI_reg_reg. + addI_reg_reg(dst, tmp1, tmp2); + %} +%} + +// Immediate Addition +instruct addI_reg_imm16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ + match(Set dst (AddI src1 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); +%} + +// Immediate Addition with 16-bit shifted operand +instruct addI_reg_immhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2) %{ + match(Set dst (AddI src1 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); +%} + +// Long Addition +instruct addL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (AddL src1 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); +%} + +// Expand does not work with above instruct. (??) +instruct addL_reg_reg_2(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + // no match-rule + effect(DEF dst, USE src1, USE 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); +%} + +instruct tree_addL_addL_addL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2, iRegLsrc src3, iRegLsrc src4) %{ + match(Set dst (AddL (AddL (AddL src1 src2) src3) src4)); + ins_cost(DEFAULT_COST*3); + + expand %{ + // FIXME: we should do this in the ideal world. + iRegLdst tmp1; + iRegLdst tmp2; + addL_reg_reg(tmp1, src1, src2); + addL_reg_reg_2(tmp2, src3, src4); // Adlc complains about orI_reg_reg. + addL_reg_reg(dst, tmp1, tmp2); + %} +%} + +// AddL + ConvL2I. +instruct addI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (ConvL2I (AddL src1 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); +%} + +// No constant pool entries required. +instruct addL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ + match(Set dst (AddL src1 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); +%} + +// Long Immediate Addition with 16-bit shifted operand. +// No constant pool entries required. +instruct addL_reg_immhi16(iRegLdst dst, iRegLsrc src1, immL32hi16 src2) %{ + match(Set dst (AddL src1 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); +%} + +// Pointer Register Addition +instruct addP_reg_reg(iRegPdst dst, iRegP_N2P src1, iRegLsrc src2) %{ + match(Set dst (AddP src1 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); +%} + +// Pointer Immediate Addition +// No constant pool entries required. +instruct addP_reg_imm16(iRegPdst dst, iRegP_N2P src1, immL16 src2) %{ + match(Set dst (AddP src1 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); +%} + +// Pointer Immediate Addition with 16-bit shifted operand. +// No constant pool entries required. +instruct addP_reg_immhi16(iRegPdst dst, iRegP_N2P src1, immL32hi16 src2) %{ + match(Set dst (AddP src1 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); +%} + +//--------------------- +// Subtraction Instructions + +// Register Subtraction +instruct subI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (SubI src1 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); +%} + +// Immediate Subtraction +// The compiler converts "x-c0" into "x+ -c0" (see SubINode::Ideal), +// so this rule seems to be unused. +instruct subI_reg_imm16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ + match(Set dst (SubI src1 src2)); + format %{ "SUBI $dst, $src1, $src2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ addi($dst$$Register, $src1$$Register, ($src2$$constant) * (-1)); + %} + ins_pipe(pipe_class_default); +%} + +// SubI from constant (using subfic). +instruct subI_imm16_reg(iRegIdst dst, immI16 src1, iRegIsrc src2) %{ + match(Set dst (SubI src1 src2)); + format %{ "SUBI $dst, $src1, $src2" %} + + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_subfic); + __ subfic($dst$$Register, $src2$$Register, $src1$$constant); + %} + ins_pipe(pipe_class_default); +%} + +// Turn the sign-bit of an integer into a 32-bit mask, 0x0...0 for +// positive integers and 0xF...F for negative ones. +instruct signmask32I_regI(iRegIdst dst, iRegIsrc src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +instruct absI_reg_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (AbsI src)); + ins_cost(DEFAULT_COST*3); + + expand %{ + iRegIdst tmp1; + iRegIdst tmp2; + signmask32I_regI(tmp1, src); + xorI_reg_reg(tmp2, tmp1, src); + subI_reg_reg(dst, tmp2, tmp1); + %} +%} + +instruct negI_regI(iRegIdst dst, immI_0 zero, iRegIsrc src2) %{ + match(Set dst (SubI zero 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); +%} + +// Long subtraction +instruct subL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (SubL src1 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); +%} + +// SubL + convL2I. +instruct subI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (ConvL2I (SubL src1 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); +%} + +// Immediate Subtraction +// The compiler converts "x-c0" into "x+ -c0" (see SubLNode::Ideal), +// so this rule seems to be unused. +// No constant pool entries required. +instruct subL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ + match(Set dst (SubL src1 src2)); + + format %{ "SUBI $dst, $src1, $src2 \t// long" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ addi($dst$$Register, $src1$$Register, ($src2$$constant) * (-1)); + %} + ins_pipe(pipe_class_default); +%} + +// Turn the sign-bit of a long into a 64-bit mask, 0x0...0 for +// positive longs and 0xF...F for negative ones. +instruct signmask64I_regI(iRegIdst dst, iRegIsrc src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Long negation +instruct negL_reg_reg(iRegLdst dst, immL_0 zero, iRegLsrc src2) %{ + match(Set dst (SubL zero 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); +%} + +// NegL + ConvL2I. +instruct negI_con0_regL(iRegIdst dst, immL_0 zero, iRegLsrc src2) %{ + match(Set dst (ConvL2I (SubL zero 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); +%} + +// Multiplication Instructions +// Integer Multiplication + +// Register Multiplication +instruct mulI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (MulI src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Immediate Multiplication +instruct mulI_reg_imm16(iRegIdst dst, iRegIsrc src1, immI16 src2) %{ + match(Set dst (MulI src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +instruct mulL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (MulL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Multiply high for optimized long division by constant. +instruct mulHighL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (MulHiL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Immediate Multiplication +instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{ + match(Set dst (MulL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Integer Division with Immediate -1: Negate. +instruct divI_reg_immIvalueMinus1(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{ + match(Set dst (DivI src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Integer Division with constant, but not -1. +// We should be able to improve this by checking the type of src2. +// It might well be that src2 is known to be positive. +instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (DivI src1 src2)); + predicate(n->in(2)->find_int_con(-1) != -1); // src2 is a constant, but not -1 + ins_cost(2*DEFAULT_COST); + + 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); +%} + +instruct cmovI_bne_negI_reg(iRegIdst dst, flagsReg crx, iRegIsrc src1) %{ + effect(USE_DEF dst, USE src1, USE crx); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +// Integer Division with Registers not containing constants. +instruct divI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (DivI src1 src2)); + ins_cost(10*DEFAULT_COST); + + expand %{ + immI16 imm %{ (int)-1 %} + flagsReg tmp1; + cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1 + divI_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2 + cmovI_bne_negI_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1 + %} +%} + +// Long Division with Immediate -1: Negate. +instruct divL_reg_immLvalueMinus1(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) %{ + match(Set dst (DivL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Long Division with constant, but not -1. +instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (DivL src1 src2)); + predicate(n->in(2)->find_long_con(-1L) != -1L); // Src2 is a constant, but not -1. + ins_cost(2*DEFAULT_COST); + + 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); +%} + +instruct cmovL_bne_negL_reg(iRegLdst dst, flagsReg crx, iRegLsrc src1) %{ + effect(USE_DEF dst, USE src1, USE crx); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +// Long Division with Registers not containing constants. +instruct divL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (DivL src1 src2)); + ins_cost(10*DEFAULT_COST); + + expand %{ + immL16 imm %{ (int)-1 %} + flagsReg tmp1; + cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1 + divL_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2 + cmovL_bne_negL_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1 + %} +%} + +// Integer Remainder with registers. +instruct modI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (ModI src1 src2)); + ins_cost(10*DEFAULT_COST); + + expand %{ + immI16 imm %{ (int)-1 %} + flagsReg tmp1; + iRegIdst tmp2; + iRegIdst tmp3; + cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1 + divI_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2 + cmovI_bne_negI_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1 + mulI_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2 + subI_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3 + %} +%} + +// Long Remainder with registers +instruct modL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 cr0) %{ + match(Set dst (ModL src1 src2)); + ins_cost(10*DEFAULT_COST); + + expand %{ + immL16 imm %{ (int)-1 %} + flagsReg tmp1; + iRegLdst tmp2; + iRegLdst tmp3; + cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1 + divL_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2 + cmovL_bne_negL_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1 + mulL_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2 + subL_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3 + %} +%} + +// Integer Shift Instructions + +// Register Shift Left + +// Clear all but the lowest #mask bits. +// Used to normalize shift amounts in registers. +instruct maskI_reg_imm(iRegIdst dst, iRegIsrc src, uimmI6 mask) %{ + // no match-rule, false predicate + effect(DEF dst, USE src, USE mask); + predicate(false); + + 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); +%} + +instruct lShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +instruct lShiftI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (LShiftI src1 src2)); + ins_cost(DEFAULT_COST*2); + expand %{ + uimmI6 mask %{ 0x3b /* clear 59 bits, keep 5 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + lShiftI_reg_reg(dst, src1, tmpI); + %} +%} + +// Register Shift Left Immediate +instruct lShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ + match(Set dst (LShiftI src1 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); +%} + +// AndI with negpow2-constant + LShiftI +instruct lShiftI_andI_immInegpow2_imm5(iRegIdst dst, iRegIsrc src1, immInegpow2 src2, uimmI5 src3) %{ + match(Set dst (LShiftI (AndI src1 src2) src3)); + predicate(UseRotateAndMaskInstructionsPPC64); + + 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); + if (maskbits >= 32) { + __ li($dst$$Register, 0); // addi + } else { + __ rlwinm($dst$$Register, $src1$$Register, src3 & 0x1f, 0, (31-maskbits) & 0x1f); + } + %} + ins_pipe(pipe_class_default); +%} + +// RShiftI + AndI with negpow2-constant + LShiftI +instruct lShiftI_andI_immInegpow2_rShiftI_imm5(iRegIdst dst, iRegIsrc src1, immInegpow2 src2, uimmI5 src3) %{ + match(Set dst (LShiftI (AndI (RShiftI src1 src3) src2) src3)); + predicate(UseRotateAndMaskInstructionsPPC64); + + 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); + if (maskbits >= 32) { + __ li($dst$$Register, 0); // addi + } else { + __ rlwinm($dst$$Register, $src1$$Register, 0, 0, (31-maskbits) & 0x1f); + } + %} + ins_pipe(pipe_class_default); +%} + +instruct lShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Register Shift Left +instruct lShiftL_regL_regI_Ex(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + match(Set dst (LShiftL src1 src2)); + ins_cost(DEFAULT_COST*2); + expand %{ + uimmI6 mask %{ 0x3a /* clear 58 bits, keep 6 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + lShiftL_regL_regI(dst, src1, tmpI); + %} +%} + +// Register Shift Left Immediate +instruct lshiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ + match(Set dst (LShiftL src1 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); +%} + +// If we shift more than 32 bits, we need not convert I2L. +instruct lShiftL_regI_immGE32(iRegLdst dst, iRegIsrc src1, uimmI6_ge32 src2) %{ + match(Set dst (LShiftL (ConvI2L src1) src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Shift a postivie int to the left. +// Clrlsldi clears the upper 32 bits and shifts. +instruct scaledPositiveI2L_lShiftL_convI2L_reg_imm6(iRegLdst dst, iRegIsrc src1, uimmI6 src2) %{ + match(Set dst (LShiftL (ConvI2L src1) src2)); + predicate(((ConvI2LNode*)(_kids[0]->_leaf))->type()->is_long()->is_positive_int()); + + 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); +%} + +instruct arShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Register Arithmetic Shift Right +instruct arShiftI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (RShiftI src1 src2)); + ins_cost(DEFAULT_COST*2); + expand %{ + uimmI6 mask %{ 0x3b /* clear 59 bits, keep 5 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + arShiftI_reg_reg(dst, src1, tmpI); + %} +%} + +// Register Arithmetic Shift Right Immediate +instruct arShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ + match(Set dst (RShiftI src1 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); +%} + +instruct arShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Register Shift Right Arithmetic Long +instruct arShiftL_regL_regI_Ex(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + match(Set dst (RShiftL src1 src2)); + ins_cost(DEFAULT_COST*2); + + expand %{ + uimmI6 mask %{ 0x3a /* clear 58 bits, keep 6 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + arShiftL_regL_regI(dst, src1, tmpI); + %} +%} + +// Register Shift Right Immediate +instruct arShiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ + match(Set dst (RShiftL src1 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); +%} + +// RShiftL + ConvL2I +instruct convL2I_arShiftL_regL_immI(iRegIdst dst, iRegLsrc src1, immI src2) %{ + match(Set dst (ConvL2I (RShiftL src1 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); +%} + +instruct urShiftI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Register Shift Right +instruct urShiftI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (URShiftI src1 src2)); + ins_cost(DEFAULT_COST*2); + + expand %{ + uimmI6 mask %{ 0x3b /* clear 59 bits, keep 5 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + urShiftI_reg_reg(dst, src1, tmpI); + %} +%} + +// Register Shift Right Immediate +instruct urShiftI_reg_imm(iRegIdst dst, iRegIsrc src1, immI src2) %{ + match(Set dst (URShiftI src1 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); +%} + +instruct urShiftL_regL_regI(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +// Register Shift Right +instruct urShiftL_regL_regI_Ex(iRegLdst dst, iRegLsrc src1, iRegIsrc src2) %{ + match(Set dst (URShiftL src1 src2)); + ins_cost(DEFAULT_COST*2); + + expand %{ + uimmI6 mask %{ 0x3a /* clear 58 bits, keep 6 */ %} + iRegIdst tmpI; + maskI_reg_imm(tmpI, src2, mask); + urShiftL_regL_regI(dst, src1, tmpI); + %} +%} + +// Register Shift Right Immediate +instruct urShiftL_regL_immI(iRegLdst dst, iRegLsrc src1, immI src2) %{ + match(Set dst (URShiftL src1 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); +%} + +// URShiftL + ConvL2I. +instruct convL2I_urShiftL_regL_immI(iRegIdst dst, iRegLsrc src1, immI src2) %{ + match(Set dst (ConvL2I (URShiftL src1 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); +%} + +// Register Shift Right Immediate with a CastP2X +instruct shrP_convP2X_reg_imm6(iRegLdst dst, iRegP_N2P src1, uimmI6 src2) %{ + match(Set dst (URShiftL (CastP2X src1) 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); +%} + +instruct sxtI_reg(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ConvL2I (ConvI2L 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); +%} + +//----------Rotate Instructions------------------------------------------------ + +// Rotate Left by 8-bit immediate +instruct rotlI_reg_immi8(iRegIdst dst, iRegIsrc src, immI8 lshift, immI8 rshift) %{ + match(Set dst (OrI (LShiftI src lshift) (URShiftI src rshift))); + predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f)); + + 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); +%} + +// Rotate Right by 8-bit immediate +instruct rotrI_reg_immi8(iRegIdst dst, iRegIsrc src, immI8 rshift, immI8 lshift) %{ + match(Set dst (OrI (URShiftI src rshift) (LShiftI src lshift))); + predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 0x1f)); + + 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); +%} + +//----------Floating Point Arithmetic Instructions----------------------------- + +// Add float single precision +instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ + match(Set dst (AddF src1 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); +%} + +// Add float double precision +instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ + match(Set dst (AddD src1 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); +%} + +// Sub float single precision +instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ + match(Set dst (SubF src1 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); +%} + +// Sub float double precision +instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ + match(Set dst (SubD src1 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); +%} + +// Mul float single precision +instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ + match(Set dst (MulF src1 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); +%} + +// Mul float double precision +instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ + match(Set dst (MulD src1 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); +%} + +// Div float single precision +instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ + match(Set dst (DivF src1 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); +%} + +// Div float double precision +instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ + match(Set dst (DivD src1 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); +%} + +// Absolute float single precision +instruct absF_reg(regF dst, regF src) %{ + match(Set dst (AbsF 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); +%} + +// Absolute float double precision +instruct absD_reg(regD dst, regD src) %{ + match(Set dst (AbsD 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); +%} + +instruct negF_reg(regF dst, regF src) %{ + match(Set dst (NegF 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); +%} + +instruct negD_reg(regD dst, regD src) %{ + match(Set dst (NegD 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); +%} + +// AbsF + NegF. +instruct negF_absF_reg(regF dst, regF src) %{ + match(Set dst (NegF (AbsF 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); +%} + +// AbsD + NegD. +instruct negD_absD_reg(regD dst, regD src) %{ + match(Set dst (NegD (AbsD 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); +%} + +// VM_Version::has_sqrt() decides if this node will be used. +// Sqrt float double precision +instruct sqrtD_reg(regD dst, regD src) %{ + match(Set dst (SqrtD 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); +%} + +// Single-precision sqrt. +instruct sqrtF_reg(regF dst, regF src) %{ + match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); + ins_cost(DEFAULT_COST); + + format %{ "FSQRTS $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_fsqrts); + __ fsqrts($dst$$FloatRegister, $src$$FloatRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct roundDouble_nop(regD dst) %{ + match(Set dst (RoundDouble dst)); + ins_cost(0); + + format %{ " -- \t// RoundDouble not needed - empty" %} + size(0); + // PPC results are already "rounded" (i.e., normal-format IEEE). + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct roundFloat_nop(regF dst) %{ + match(Set dst (RoundFloat dst)); + ins_cost(0); + + format %{ " -- \t// RoundFloat not needed - empty" %} + size(0); + // PPC results are already "rounded" (i.e., normal-format IEEE). + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +//----------Logical Instructions----------------------------------------------- + +// And Instructions + +// Register And +instruct andI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (AndI src1 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); +%} + +// Immediate And +instruct andI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2, flagsRegCR0 cr0) %{ + match(Set dst (AndI src1 src2)); + effect(KILL cr0); + + 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); + %} + ins_pipe(pipe_class_default); +%} + +// Immediate And where the immediate is a negative power of 2. +instruct andI_reg_immInegpow2(iRegIdst dst, iRegIsrc src1, immInegpow2 src2) %{ + match(Set dst (AndI src1 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); +%} + +instruct andI_reg_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immIpow2minus1 src2) %{ + match(Set dst (AndI src1 src2)); + 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); +%} + +instruct andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src1, immIpowerOf2 src2) %{ + match(Set dst (AndI src1 src2)); + predicate(UseRotateAndMaskInstructionsPPC64); + 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); + %} + ins_pipe(pipe_class_default); +%} + +// Register And Long +instruct andL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (AndL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Immediate And long +instruct andL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2, flagsRegCR0 cr0) %{ + match(Set dst (AndL src1 src2)); + effect(KILL cr0); + ins_cost(DEFAULT_COST); + + 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); + %} + ins_pipe(pipe_class_default); +%} + +// Immediate And Long where the immediate is a negative power of 2. +instruct andL_reg_immLnegpow2(iRegLdst dst, iRegLsrc src1, immLnegpow2 src2) %{ + match(Set dst (AndL src1 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); +%} + +instruct andL_reg_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immLpow2minus1 src2) %{ + match(Set dst (AndL src1 src2)); + 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); +%} + +// AndL + ConvL2I. +instruct convL2I_andL_reg_immLpow2minus1(iRegIdst dst, iRegLsrc src1, immLpow2minus1 src2) %{ + match(Set dst (ConvL2I (AndL src1 src2))); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Or Instructions + +// Register Or +instruct orI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (OrI src1 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); +%} + +// Expand does not work with above instruct. (??) +instruct orI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule + effect(DEF dst, USE src1, USE 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); +%} + +instruct tree_orI_orI_orI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, iRegIsrc src3, iRegIsrc src4) %{ + match(Set dst (OrI (OrI (OrI src1 src2) src3) src4)); + ins_cost(DEFAULT_COST*3); + + expand %{ + // FIXME: we should do this in the ideal world. + iRegIdst tmp1; + iRegIdst tmp2; + orI_reg_reg(tmp1, src1, src2); + orI_reg_reg_2(tmp2, src3, src4); // Adlc complains about orI_reg_reg. + orI_reg_reg(dst, tmp1, tmp2); + %} +%} + +// Immediate Or +instruct orI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2) %{ + match(Set dst (OrI src1 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); +%} + +// Register Or Long +instruct orL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (OrL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// OrL + ConvL2I. +instruct orI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (ConvL2I (OrL src1 src2))); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Immediate Or long +instruct orL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 con) %{ + match(Set dst (OrL src1 con)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Xor Instructions + +// Register Xor +instruct xorI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (XorI src1 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); +%} + +// Expand does not work with above instruct. (??) +instruct xorI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + // no match-rule + effect(DEF dst, USE src1, USE 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); +%} + +instruct tree_xorI_xorI_xorI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, iRegIsrc src3, iRegIsrc src4) %{ + match(Set dst (XorI (XorI (XorI src1 src2) src3) src4)); + ins_cost(DEFAULT_COST*3); + + expand %{ + // FIXME: we should do this in the ideal world. + iRegIdst tmp1; + iRegIdst tmp2; + xorI_reg_reg(tmp1, src1, src2); + xorI_reg_reg_2(tmp2, src3, src4); // Adlc complains about xorI_reg_reg. + xorI_reg_reg(dst, tmp1, tmp2); + %} +%} + +// Immediate Xor +instruct xorI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2) %{ + match(Set dst (XorI src1 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); +%} + +// Register Xor Long +instruct xorL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (XorL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// XorL + ConvL2I. +instruct xorI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (ConvL2I (XorL src1 src2))); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Immediate Xor Long +instruct xorL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2) %{ + match(Set dst (XorL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +instruct notI_reg(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{ + match(Set dst (XorI src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +instruct notL_reg(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) %{ + match(Set dst (XorL src1 src2)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// And-complement +instruct andcI_reg_reg(iRegIdst dst, iRegIsrc src1, immI_minus1 src2, iRegIsrc src3) %{ + match(Set dst (AndI (XorI src1 src2) src3)); + ins_cost(DEFAULT_COST); + + format %{ "ANDW $dst, xori($src1, $src2), $src3" %} + size(4); + ins_encode( enc_andc(dst, src3, src1) ); + ins_pipe(pipe_class_default); +%} + +// And-complement +instruct andcL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ + // no match-rule, false predicate + effect(DEF dst, USE src1, USE src2); + predicate(false); + + 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); +%} + +//----------Moves between int/long and float/double---------------------------- +// +// The following rules move values from int/long registers/stack-locations +// to float/double registers/stack-locations and vice versa, without doing any +// conversions. These rules are used to implement the bit-conversion methods +// of java.lang.Float etc., e.g. +// int floatToIntBits(float value) +// float intBitsToFloat(int bits) +// +// Notes on the implementation on ppc64: +// We only provide rules which move between a register and a stack-location, +// because we always have to go through memory when moving between a float +// register and an integer register. + +//---------- Chain stack slots between similar types -------- + +// These are needed so that the rules below can match. + +// Load integer from stack slot +instruct stkI_to_regI(iRegIdst dst, stackSlotI src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $src" %} + size(4); + ins_encode( enc_lwz(dst, src) ); + ins_pipe(pipe_class_memory); +%} + +// Store integer to stack slot +instruct regI_to_stkI(stackSlotI dst, iRegIsrc src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + format %{ "STW $src, $dst \t// stk" %} + size(4); + ins_encode( enc_stw(src, dst) ); // rs=rt + ins_pipe(pipe_class_memory); +%} + +// Load long from stack slot +instruct stkL_to_regL(iRegLdst dst, stackSlotL src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + format %{ "LD $dst, $src \t// long" %} + size(4); + ins_encode( enc_ld(dst, src) ); + ins_pipe(pipe_class_memory); +%} + +// Store long to stack slot +instruct regL_to_stkL(stackSlotL dst, iRegLsrc src) %{ + match(Set dst src); + ins_cost(MEMORY_REF_COST); + + format %{ "STD $src, $dst \t// long" %} + size(4); + ins_encode( enc_std(src, dst) ); // rs=rt + ins_pipe(pipe_class_memory); +%} + +//----------Moves between int and float + +// Move float value from float stack-location to integer register. +instruct moveF2I_stack_reg(iRegIdst dst, stackSlotF src) %{ + match(Set dst (MoveF2I src)); + ins_cost(MEMORY_REF_COST); + + format %{ "LWZ $dst, $src \t// MoveF2I" %} + size(4); + ins_encode( enc_lwz(dst, src) ); + ins_pipe(pipe_class_memory); +%} + +// Move float value from float register to integer stack-location. +instruct moveF2I_reg_stack(stackSlotI dst, regF src) %{ + match(Set dst (MoveF2I src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STFS $src, $dst \t// MoveF2I" %} + size(4); + ins_encode( enc_stfs(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +// Move integer value from integer stack-location to float register. +instruct moveI2F_stack_reg(regF dst, stackSlotI src) %{ + match(Set dst (MoveI2F src)); + ins_cost(MEMORY_REF_COST); + + 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); + %} + ins_pipe(pipe_class_memory); +%} + +// Move integer value from integer register to float stack-location. +instruct moveI2F_reg_stack(stackSlotF dst, iRegIsrc src) %{ + match(Set dst (MoveI2F src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STW $src, $dst \t// MoveI2F" %} + size(4); + ins_encode( enc_stw(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +//----------Moves between long and float + +instruct moveF2L_reg_stack(stackSlotL dst, regF src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + format %{ "storeD $src, $dst \t// STACK" %} + size(4); + ins_encode( enc_stfd(src, dst) ); + ins_pipe(pipe_class_default); +%} + +//----------Moves between long and double + +// Move double value from double stack-location to long register. +instruct moveD2L_stack_reg(iRegLdst dst, stackSlotD src) %{ + match(Set dst (MoveD2L src)); + ins_cost(MEMORY_REF_COST); + size(4); + format %{ "LD $dst, $src \t// MoveD2L" %} + ins_encode( enc_ld(dst, src) ); + ins_pipe(pipe_class_memory); +%} + +// Move double value from double register to long stack-location. +instruct moveD2L_reg_stack(stackSlotL dst, regD src) %{ + match(Set dst (MoveD2L src)); + effect(DEF dst, USE src); + ins_cost(MEMORY_REF_COST); + + format %{ "STFD $src, $dst \t// MoveD2L" %} + size(4); + ins_encode( enc_stfd(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +// Move long value from long stack-location to double register. +instruct moveL2D_stack_reg(regD dst, stackSlotL src) %{ + match(Set dst (MoveL2D src)); + ins_cost(MEMORY_REF_COST); + + format %{ "LFD $dst, $src \t// MoveL2D" %} + size(4); + ins_encode( enc_lfd(dst, src) ); + ins_pipe(pipe_class_memory); +%} + +// Move long value from long register to double stack-location. +instruct moveL2D_reg_stack(stackSlotD dst, iRegLsrc src) %{ + match(Set dst (MoveL2D src)); + ins_cost(MEMORY_REF_COST); + + format %{ "STD $src, $dst \t// MoveL2D" %} + size(4); + ins_encode( enc_std(src, dst) ); + ins_pipe(pipe_class_memory); +%} + +//----------Register Move Instructions----------------------------------------- + +// Replicate for Superword + +instruct moveReg(iRegLdst dst, iRegIsrc src) %{ + predicate(false); + effect(DEF dst, USE 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); +%} + +//----------Cast instructions (Java-level type cast)--------------------------- + +// Cast Long to Pointer for unsafe natives. +instruct castX2P(iRegPdst dst, iRegLsrc src) %{ + match(Set dst (CastX2P 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); +%} + +// Cast Pointer to Long for unsafe natives. +instruct castP2X(iRegLdst dst, iRegP_N2P src) %{ + match(Set dst (CastP2X 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); +%} + +instruct castPP(iRegPdst dst) %{ + match(Set dst (CastPP dst)); + format %{ " -- \t// castPP of $dst" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct castII(iRegIdst dst) %{ + match(Set dst (CastII dst)); + format %{ " -- \t// castII of $dst" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +instruct checkCastPP(iRegPdst dst) %{ + match(Set dst (CheckCastPP dst)); + format %{ " -- \t// checkcastPP of $dst" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +//----------Convert instructions----------------------------------------------- + +// Convert to boolean. + +// int_to_bool(src) : { 1 if src != 0 +// { 0 else +// +// strategy: +// 1) Count leading zeros of 32 bit-value src, +// this returns 32 (0b10.0000) iff src == 0 and <32 otherwise. +// 2) Shift 5 bits to the right, result is 0b1 iff src == 0, 0b0 otherwise. +// 3) Xori the result to get 0b1 if src != 0 and 0b0 if src == 0. + +// convI2Bool +instruct convI2Bool_reg__cntlz_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (Conv2B src)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI shiftAmount %{ 0x5 %} + uimmI16 mask %{ 0x1 %} + iRegIdst tmp1; + iRegIdst tmp2; + countLeadingZerosI(tmp1, src); + urShiftI_reg_imm(tmp2, tmp1, shiftAmount); + xorI_reg_uimm16(dst, tmp2, mask); + %} +%} + +instruct convI2Bool_reg__cmove(iRegIdst dst, iRegIsrc src, flagsReg crx) %{ + match(Set dst (Conv2B src)); + effect(TEMP crx); + predicate(!UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + format %{ "CMPWI $crx, $src, #0 \t// convI2B" + "LI $dst, #0\n\t" + "BEQ $crx, done\n\t" + "LI $dst, #1\n" + "done:" %} + size(16); + ins_encode( enc_convI2B_regI__cmove(dst, src, crx, 0x0, 0x1) ); + ins_pipe(pipe_class_compare); +%} + +// ConvI2B + XorI +instruct xorI_convI2Bool_reg_immIvalue1__cntlz_Ex(iRegIdst dst, iRegIsrc src, immI_1 mask) %{ + match(Set dst (XorI (Conv2B src) mask)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI shiftAmount %{ 0x5 %} + iRegIdst tmp1; + countLeadingZerosI(tmp1, src); + urShiftI_reg_imm(dst, tmp1, shiftAmount); + %} +%} + +instruct xorI_convI2Bool_reg_immIvalue1__cmove(iRegIdst dst, iRegIsrc src, flagsReg crx, immI_1 mask) %{ + match(Set dst (XorI (Conv2B src) mask)); + effect(TEMP crx); + predicate(!UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + format %{ "CMPWI $crx, $src, #0 \t// Xor(convI2B($src), $mask)" + "LI $dst, #1\n\t" + "BEQ $crx, done\n\t" + "LI $dst, #0\n" + "done:" %} + size(16); + ins_encode( enc_convI2B_regI__cmove(dst, src, crx, 0x1, 0x0) ); + ins_pipe(pipe_class_compare); +%} + +// AndI 0b0..010..0 + ConvI2B +instruct convI2Bool_andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src, immIpowerOf2 mask) %{ + match(Set dst (Conv2B (AndI src mask))); + predicate(UseRotateAndMaskInstructionsPPC64); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Convert pointer to boolean. +// +// ptr_to_bool(src) : { 1 if src != 0 +// { 0 else +// +// strategy: +// 1) Count leading zeros of 64 bit-value src, +// this returns 64 (0b100.0000) iff src == 0 and <64 otherwise. +// 2) Shift 6 bits to the right, result is 0b1 iff src == 0, 0b0 otherwise. +// 3) Xori the result to get 0b1 if src != 0 and 0b0 if src == 0. + +// ConvP2B +instruct convP2Bool_reg__cntlz_Ex(iRegIdst dst, iRegP_N2P src) %{ + match(Set dst (Conv2B src)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI shiftAmount %{ 0x6 %} + uimmI16 mask %{ 0x1 %} + iRegIdst tmp1; + iRegIdst tmp2; + countLeadingZerosP(tmp1, src); + urShiftI_reg_imm(tmp2, tmp1, shiftAmount); + xorI_reg_uimm16(dst, tmp2, mask); + %} +%} + +instruct convP2Bool_reg__cmove(iRegIdst dst, iRegP_N2P src, flagsReg crx) %{ + match(Set dst (Conv2B src)); + effect(TEMP crx); + predicate(!UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + format %{ "CMPDI $crx, $src, #0 \t// convP2B" + "LI $dst, #0\n\t" + "BEQ $crx, done\n\t" + "LI $dst, #1\n" + "done:" %} + size(16); + ins_encode( enc_convP2B_regP__cmove(dst, src, crx, 0x0, 0x1) ); + ins_pipe(pipe_class_compare); +%} + +// ConvP2B + XorI +instruct xorI_convP2Bool_reg__cntlz_Ex(iRegIdst dst, iRegP_N2P src, immI_1 mask) %{ + match(Set dst (XorI (Conv2B src) mask)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI shiftAmount %{ 0x6 %} + iRegIdst tmp1; + countLeadingZerosP(tmp1, src); + urShiftI_reg_imm(dst, tmp1, shiftAmount); + %} +%} + +instruct xorI_convP2Bool_reg_immIvalue1__cmove(iRegIdst dst, iRegP_N2P src, flagsReg crx, immI_1 mask) %{ + match(Set dst (XorI (Conv2B src) mask)); + effect(TEMP crx); + predicate(!UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + format %{ "CMPDI $crx, $src, #0 \t// XorI(convP2B($src), $mask)" + "LI $dst, #1\n\t" + "BEQ $crx, done\n\t" + "LI $dst, #0\n" + "done:" %} + size(16); + ins_encode( enc_convP2B_regP__cmove(dst, src, crx, 0x1, 0x0) ); + ins_pipe(pipe_class_compare); +%} + +// if src1 < src2, return -1 else return 0 +instruct cmpLTMask_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (CmpLTMask src1 src2)); + ins_cost(DEFAULT_COST*4); + + expand %{ + iRegIdst src1s; + iRegIdst src2s; + iRegIdst diff; + sxtI_reg(src1s, src1); // ensure proper sign extention + sxtI_reg(src2s, src2); // ensure proper sign extention + subI_reg_reg(diff, src1s, src2s); + // Need to consider >=33 bit result, therefore we need signmaskL. + signmask64I_regI(dst, diff); + %} +%} + +instruct cmpLTMask_reg_immI0(iRegIdst dst, iRegIsrc src1, immI_0 src2) %{ + match(Set dst (CmpLTMask src1 src2)); // if src1 < src2, return -1 else return 0 + 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); +%} + +//----------Arithmetic Conversion Instructions--------------------------------- + +// Convert to Byte -- nop +// Convert to Short -- nop + +// Convert to Int + +instruct convB2I_reg(iRegIdst dst, iRegIsrc src, immI_24 amount) %{ + match(Set dst (RShiftI (LShiftI src amount) 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); +%} + +// LShiftI 16 + RShiftI 16 converts short to int. +instruct convS2I_reg(iRegIdst dst, iRegIsrc src, immI_16 amount) %{ + match(Set dst (RShiftI (LShiftI src amount) 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); +%} + +// ConvL2I + ConvI2L: Sign extend int in long register. +instruct sxtI_L2L_reg(iRegLdst dst, iRegLsrc src) %{ + match(Set dst (ConvI2L (ConvL2I 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); +%} + +instruct convL2I_reg(iRegIdst dst, iRegLsrc src) %{ + match(Set dst (ConvL2I 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); +%} + +instruct convD2IRaw_regD(regD dst, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +instruct cmovI_bso_stackSlotL(iRegIdst dst, flagsReg crx, stackSlotL src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovI_bso_stackSlotL_conLvalue0_Ex(iRegIdst dst, flagsReg crx, stackSlotL mem) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE mem); + predicate(false); + + format %{ "CmovI $dst, $crx, $mem \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region dst crx mem + // \ | | / + // dst=cmovI_bso_stackSlotL_conLvalue0 + // + // with + // + // region dst + // \ / + // dst=loadConI16(0) + // | + // ^ region dst crx mem + // | \ | | / + // dst=cmovI_bso_stackSlotL + // + + // Create new nodes. + MachNode *m1 = new (C) loadConI16Node(); + MachNode *m2 = new (C) cmovI_bso_stackSlotLNode(); + + // inputs for new nodes + m1->add_req(n_region); + m2->add_req(n_region, n_crx, n_mem); + + // precedences for new nodes + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_dst; + m1->_opnds[1] = new (C) immI16Oper(0); + + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_crx; + m2->_opnds[2] = op_mem; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + +// Double to Int conversion, NaN is mapped to 0. +instruct convD2I_reg_ExEx(iRegIdst dst, regD src) %{ + match(Set dst (ConvD2I src)); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + stackSlotL tmpS; + flagsReg crx; + cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convD2IRaw_regD(tmpD, src); // Convert float to int (speculated). + moveD2L_reg_stack(tmpS, tmpD); // Store float to stack (speculated). + cmovI_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check. + %} +%} + +instruct convF2IRaw_regF(regF dst, regF src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Float to Int conversion, NaN is mapped to 0. +instruct convF2I_regF_ExEx(iRegIdst dst, regF src) %{ + match(Set dst (ConvF2I src)); + ins_cost(DEFAULT_COST); + + expand %{ + regF tmpF; + stackSlotL tmpS; + flagsReg crx; + cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convF2IRaw_regF(tmpF, src); // Convert float to int (speculated). + moveF2L_reg_stack(tmpS, tmpF); // Store float to stack (speculated). + cmovI_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check. + %} +%} + +// Convert to Long + +instruct convI2L_reg(iRegLdst dst, iRegIsrc src) %{ + match(Set dst (ConvI2L 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); +%} + +// Zero-extend: convert unsigned int to long (convUI2L). +instruct zeroExtendL_regI(iRegLdst dst, iRegIsrc src, immL_32bits mask) %{ + match(Set dst (AndL (ConvI2L src) mask)); + ins_cost(DEFAULT_COST); + + 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); +%} + +// Zero-extend: convert unsigned int to long in long register. +instruct zeroExtendL_regL(iRegLdst dst, iRegLsrc src, immL_32bits mask) %{ + match(Set dst (AndL src mask)); + ins_cost(DEFAULT_COST); + + 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); +%} + +instruct convF2LRaw_regF(regF dst, regF src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +instruct cmovL_bso_stackSlotL(iRegLdst dst, flagsReg crx, stackSlotL src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) ); + ins_pipe(pipe_class_default); +%} + +instruct cmovL_bso_stackSlotL_conLvalue0_Ex(iRegLdst dst, flagsReg crx, stackSlotL mem) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE mem); + predicate(false); + + format %{ "CmovL $dst, $crx, $mem \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region dst crx mem + // \ | | / + // dst=cmovL_bso_stackSlotL_conLvalue0 + // + // with + // + // region dst + // \ / + // dst=loadConL16(0) + // | + // ^ region dst crx mem + // | \ | | / + // dst=cmovL_bso_stackSlotL + // + + // Create new nodes. + MachNode *m1 = new (C) loadConL16Node(); + MachNode *m2 = new (C) cmovL_bso_stackSlotLNode(); + + // inputs for new nodes + m1->add_req(n_region); + m2->add_req(n_region, n_crx, n_mem); + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_dst; + m1->_opnds[1] = new (C) immL16Oper(0); + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_crx; + m2->_opnds[2] = op_mem; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + +// Float to Long conversion, NaN is mapped to 0. +instruct convF2L_reg_ExEx(iRegLdst dst, regF src) %{ + match(Set dst (ConvF2L src)); + ins_cost(DEFAULT_COST); + + expand %{ + regF tmpF; + stackSlotL tmpS; + flagsReg crx; + cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convF2LRaw_regF(tmpF, src); // Convert float to long (speculated). + moveF2L_reg_stack(tmpS, tmpF); // Store float to stack (speculated). + cmovL_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check. + %} +%} + +instruct convD2LRaw_regD(regD dst, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Double to Long conversion, NaN is mapped to 0. +instruct convD2L_reg_ExEx(iRegLdst dst, regD src) %{ + match(Set dst (ConvD2L src)); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + stackSlotL tmpS; + flagsReg crx; + cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convD2LRaw_regD(tmpD, src); // Convert float to long (speculated). + moveD2L_reg_stack(tmpS, tmpD); // Store float to stack (speculated). + cmovL_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check. + %} +%} + +// Convert to Float + +// Placed here as needed in expand. +instruct convL2DRaw_regD(regD dst, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Placed here as needed in expand. +instruct convD2F_reg(regF dst, regD src) %{ + match(Set dst (ConvD2F 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); +%} + +// Integer to Float conversion. +instruct convI2F_ireg_Ex(regF dst, iRegIsrc src) %{ + match(Set dst (ConvI2F src)); + predicate(!VM_Version::has_fcfids()); + ins_cost(DEFAULT_COST); + + expand %{ + iRegLdst tmpL; + stackSlotL tmpS; + regD tmpD; + regD tmpD2; + convI2L_reg(tmpL, src); // Sign-extension int to long. + regL_to_stkL(tmpS, tmpL); // Store long to stack. + moveL2D_stack_reg(tmpD, tmpS); // Load long into double register. + convL2DRaw_regD(tmpD2, tmpD); // Convert to double. + convD2F_reg(dst, tmpD2); // Convert double to float. + %} +%} + +instruct convL2FRaw_regF(regF dst, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + 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); +%} + +// Integer to Float conversion. Special version for Power7. +instruct convI2F_ireg_fcfids_Ex(regF dst, iRegIsrc src) %{ + match(Set dst (ConvI2F src)); + predicate(VM_Version::has_fcfids()); + ins_cost(DEFAULT_COST); + + expand %{ + iRegLdst tmpL; + stackSlotL tmpS; + regD tmpD; + convI2L_reg(tmpL, src); // Sign-extension int to long. + regL_to_stkL(tmpS, tmpL); // Store long to stack. + moveL2D_stack_reg(tmpD, tmpS); // Load long into double register. + convL2FRaw_regF(dst, tmpD); // Convert to float. + %} +%} + +// L2F to avoid runtime call. +instruct convL2F_ireg_fcfids_Ex(regF dst, iRegLsrc src) %{ + match(Set dst (ConvL2F src)); + predicate(VM_Version::has_fcfids()); + ins_cost(DEFAULT_COST); + + expand %{ + stackSlotL tmpS; + regD tmpD; + regL_to_stkL(tmpS, src); // Store long to stack. + moveL2D_stack_reg(tmpD, tmpS); // Load long into double register. + convL2FRaw_regF(dst, tmpD); // Convert to float. + %} +%} + +// Moved up as used in expand. +//instruct convD2F_reg(regF dst, regD src) %{%} + +// Convert to Double + +// Integer to Double conversion. +instruct convI2D_reg_Ex(regD dst, iRegIsrc src) %{ + match(Set dst (ConvI2D src)); + ins_cost(DEFAULT_COST); + + expand %{ + iRegLdst tmpL; + stackSlotL tmpS; + regD tmpD; + convI2L_reg(tmpL, src); // Sign-extension int to long. + regL_to_stkL(tmpS, tmpL); // Store long to stack. + moveL2D_stack_reg(tmpD, tmpS); // Load long into double register. + convL2DRaw_regD(dst, tmpD); // Convert to double. + %} +%} + +// Long to Double conversion +instruct convL2D_reg_Ex(regD dst, stackSlotL src) %{ + match(Set dst (ConvL2D src)); + ins_cost(DEFAULT_COST + MEMORY_REF_COST); + + expand %{ + regD tmpD; + moveL2D_stack_reg(tmpD, src); + convL2DRaw_regD(dst, tmpD); + %} +%} + +instruct convF2D_reg(regD dst, regF src) %{ + match(Set dst (ConvF2D 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); +%} + +//----------Control Flow Instructions------------------------------------------ +// Compare Instructions + +// Compare Integers +instruct cmpI_reg_reg(flagsReg crx, iRegIsrc src1, iRegIsrc src2) %{ + match(Set crx (CmpI src1 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); +%} + +instruct cmpI_reg_imm16(flagsReg crx, iRegIsrc src1, immI16 src2) %{ + match(Set crx (CmpI src1 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); +%} + +// (src1 & src2) == 0? +instruct testI_reg_imm(flagsRegCR0 cr0, iRegIsrc src1, uimmI16 src2, immI_0 zero) %{ + match(Set cr0 (CmpI (AndI src1 src2) zero)); + // r0 is killed + format %{ "ANDI R0, $src1, $src2 \t// BTST int" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_andi_); + // FIXME: avoid andi_ ? + __ andi_(R0, $src1$$Register, $src2$$constant); + %} + ins_pipe(pipe_class_compare); +%} + +instruct cmpL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{ + match(Set crx (CmpL src1 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); +%} + +instruct cmpL_reg_imm16(flagsReg crx, iRegLsrc src1, immL16 src2) %{ + match(Set crx (CmpL src1 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); +%} + +instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zero) %{ + match(Set cr0 (CmpL (AndL src1 src2) zero)); + // r0 is killed + 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); +%} + +instruct testL_reg_imm(flagsRegCR0 cr0, iRegLsrc src1, uimmL16 src2, immL_0 zero) %{ + match(Set cr0 (CmpL (AndL src1 src2) zero)); + // r0 is killed + format %{ "ANDI R0, $src1, $src2 \t// BTST long" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_andi_); + // FIXME: avoid andi_ ? + __ andi_(R0, $src1$$Register, $src2$$constant); + %} + ins_pipe(pipe_class_compare); +%} + +instruct cmovI_conIvalueMinus1_conIvalue1(iRegIdst dst, flagsReg crx) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +instruct cmovI_conIvalueMinus1_conIvalue0_conIvalue1_Ex(iRegIdst dst, flagsReg crx) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx); + predicate(false); + + format %{ "CmovI $crx, $dst, -1, 0, +1 \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region crx + // \ | + // dst=cmovI_conIvalueMinus1_conIvalue0_conIvalue1 + // + // with + // + // region + // \ + // dst=loadConI16(0) + // | + // ^ region crx + // | \ | + // dst=cmovI_conIvalueMinus1_conIvalue1 + // + + // Create new nodes. + MachNode *m1 = new (C) loadConI16Node(); + MachNode *m2 = new (C) cmovI_conIvalueMinus1_conIvalue1Node(); + + // inputs for new nodes + m1->add_req(n_region); + m2->add_req(n_region, n_crx); + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_dst; + m1->_opnds[1] = new (C) immI16Oper(0); + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_crx; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + +// Manifest a CmpL3 result in an integer register. Very painful. +// This is the test to avoid. +// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) +instruct cmpL3_reg_reg_ExEx(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{ + match(Set dst (CmpL3 src1 src2)); + ins_cost(DEFAULT_COST*5+BRANCH_COST); + + expand %{ + flagsReg tmp1; + cmpL_reg_reg(tmp1, src1, src2); + cmovI_conIvalueMinus1_conIvalue0_conIvalue1_Ex(dst, tmp1); + %} +%} + +// Implicit range checks. +// A range check in the ideal world has one of the following shapes: +// - (If le (CmpU length index)), (IfTrue throw exception) +// - (If lt (CmpU index length)), (IfFalse throw exception) +// +// Match range check 'If le (CmpU length index)'. +instruct rangeCheck_iReg_uimm15(cmpOp cmp, iRegIsrc src_length, uimmI15 index, label labl) %{ + match(If cmp (CmpU src_length index)); + effect(USE labl); + predicate(TrapBasedRangeChecks && + _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le && + PROB_UNLIKELY(_leaf->as_If()->_prob) >= PROB_ALWAYS && + (Matcher::branches_to_uncommon_trap(_leaf))); + + ins_is_TrapBasedCheckNode(true); + + 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 { + // Both successors are uncommon traps, probability is 0. + // Node got flipped during fixup flow. + assert($cmp$$cmpcode == 0x9, "must be greater"); + __ trap_range_check_g($src_length$$Register, $index$$constant); + } + %} + ins_pipe(pipe_class_trap); +%} + +// Match range check 'If lt (CmpU index length)'. +instruct rangeCheck_iReg_iReg(cmpOp cmp, iRegIsrc src_index, iRegIsrc src_length, label labl) %{ + match(If cmp (CmpU src_index src_length)); + effect(USE labl); + predicate(TrapBasedRangeChecks && + _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt && + _leaf->as_If()->_prob >= PROB_ALWAYS && + (Matcher::branches_to_uncommon_trap(_leaf))); + + ins_is_TrapBasedCheckNode(true); + + 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 { + // Both successors are uncommon traps, probability is 0. + // Node got flipped during fixup flow. + assert($cmp$$cmpcode == 0x8, "must be less"); + __ trap_range_check_l($src_index$$Register, $src_length$$Register); + } + %} + ins_pipe(pipe_class_trap); +%} + +// Match range check 'If lt (CmpU index length)'. +instruct rangeCheck_uimm15_iReg(cmpOp cmp, iRegIsrc src_index, uimmI15 length, label labl) %{ + match(If cmp (CmpU src_index length)); + effect(USE labl); + predicate(TrapBasedRangeChecks && + _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt && + _leaf->as_If()->_prob >= PROB_ALWAYS && + (Matcher::branches_to_uncommon_trap(_leaf))); + + ins_is_TrapBasedCheckNode(true); + + 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 { + // Both successors are uncommon traps, probability is 0. + // Node got flipped during fixup flow. + assert($cmp$$cmpcode == 0x8, "must be less"); + __ trap_range_check_l($src_index$$Register, $length$$constant); + } + %} + ins_pipe(pipe_class_trap); +%} + +instruct compU_reg_reg(flagsReg crx, iRegIsrc src1, iRegIsrc src2) %{ + match(Set crx (CmpU src1 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); +%} + +instruct compU_reg_uimm16(flagsReg crx, iRegIsrc src1, uimmI16 src2) %{ + match(Set crx (CmpU src1 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); +%} + +// Implicit zero checks (more implicit null checks). +// No constant pool entries required. +instruct zeroCheckN_iReg_imm0(cmpOp cmp, iRegNsrc value, immN_0 zero, label labl) %{ + match(If cmp (CmpN value zero)); + effect(USE labl); + predicate(TrapBasedNullChecks && + _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne && + _leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) && + Matcher::branches_to_uncommon_trap(_leaf)); + ins_cost(1); + + ins_is_TrapBasedCheckNode(true); + + 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 { + // Both successors are uncommon traps, probability is 0. + // Node got flipped during fixup flow. + assert($cmp$$cmpcode == 0x2 , "must be equal(0xA) or notEqual(0x2)"); + __ trap_null_check($value$$Register, Assembler::traptoGreaterThanUnsigned); + } + %} + ins_pipe(pipe_class_trap); +%} + +// Compare narrow oops. +instruct cmpN_reg_reg(flagsReg crx, iRegNsrc src1, iRegNsrc src2) %{ + match(Set crx (CmpN src1 src2)); + + size(4); + ins_cost(DEFAULT_COST); + 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); +%} + +instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{ + match(Set crx (CmpN src1 src2)); + // Make this more expensive than zeroCheckN_iReg_imm0. + ins_cost(DEFAULT_COST); + + 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); +%} + +// Implicit zero checks (more implicit null checks). +// No constant pool entries required. +instruct zeroCheckP_reg_imm0(cmpOp cmp, iRegP_N2P value, immP_0 zero, label labl) %{ + match(If cmp (CmpP value zero)); + effect(USE labl); + predicate(TrapBasedNullChecks && + _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne && + _leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) && + Matcher::branches_to_uncommon_trap(_leaf)); + + ins_is_TrapBasedCheckNode(true); + + 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 { + // Both successors are uncommon traps, probability is 0. + // Node got flipped during fixup flow. + assert($cmp$$cmpcode == 0x2 , "must be equal(0xA) or notEqual(0x2)"); + __ trap_null_check($value$$Register, Assembler::traptoGreaterThanUnsigned); + } + %} + ins_pipe(pipe_class_trap); +%} + +// Compare Pointers +instruct cmpP_reg_reg(flagsReg crx, iRegP_N2P src1, iRegP_N2P src2) %{ + match(Set crx (CmpP src1 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); +%} + +// Used in postalloc expand. +instruct cmpP_reg_imm16(flagsReg crx, iRegPsrc src1, immL16 src2) %{ + // This match rule prevents reordering of node before a safepoint. + // This only makes sense if this instructions is used exclusively + // for the expansion of EncodeP! + match(Set crx (CmpP src1 src2)); + predicate(false); + + 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); +%} + +//----------Float Compares---------------------------------------------------- + +instruct cmpFUnordered_reg_reg(flagsReg crx, regF src1, regF src2) %{ + // no match-rule, false predicate + effect(DEF crx, USE src1, USE src2); + predicate(false); + + 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); +%} + +instruct cmov_bns_less(flagsReg crx) %{ + // no match-rule, false predicate + effect(DEF crx); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + 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); + 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); +%} + +// Compare floating, generate condition code. +instruct cmpF_reg_reg_Ex(flagsReg crx, regF src1, regF src2) %{ + // FIXME: should we match 'If cmp (CmpF src1 src2))' ?? + // + // The following code sequence occurs a lot in mpegaudio: + // + // block BXX: + // 0: instruct cmpFUnordered_reg_reg (cmpF_reg_reg-0): + // cmpFUrd CCR6, F11, F9 + // 4: instruct cmov_bns_less (cmpF_reg_reg-1): + // cmov CCR6 + // 8: instruct branchConSched: + // B_FARle CCR6, B56 P=0.500000 C=-1.000000 + match(Set crx (CmpF src1 src2)); + ins_cost(DEFAULT_COST+BRANCH_COST); + + format %{ "CmpF $crx, $src1, $src2 \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region src1 src2 + // \ | | + // crx=cmpF_reg_reg + // + // with + // + // region src1 src2 + // \ | | + // crx=cmpFUnordered_reg_reg + // | + // ^ region + // | \ + // crx=cmov_bns_less + // + + // Create new nodes. + MachNode *m1 = new (C) cmpFUnordered_reg_regNode(); + MachNode *m2 = new (C) cmov_bns_lessNode(); + + // inputs for new nodes + m1->add_req(n_region, n_src1, n_src2); + m2->add_req(n_region); + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_crx; + m1->_opnds[1] = op_src1; + m1->_opnds[2] = op_src2; + m2->_opnds[0] = op_crx; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + +// Compare float, generate -1,0,1 +instruct cmpF3_reg_reg_ExEx(iRegIdst dst, regF src1, regF src2) %{ + match(Set dst (CmpF3 src1 src2)); + ins_cost(DEFAULT_COST*5+BRANCH_COST); + + expand %{ + flagsReg tmp1; + cmpFUnordered_reg_reg(tmp1, src1, src2); + cmovI_conIvalueMinus1_conIvalue0_conIvalue1_Ex(dst, tmp1); + %} +%} + +instruct cmpDUnordered_reg_reg(flagsReg crx, regD src1, regD src2) %{ + // no match-rule, false predicate + effect(DEF crx, USE src1, USE src2); + predicate(false); + + 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); +%} + +instruct cmpD_reg_reg_Ex(flagsReg crx, regD src1, regD src2) %{ + match(Set crx (CmpD src1 src2)); + ins_cost(DEFAULT_COST+BRANCH_COST); + + format %{ "CmpD $crx, $src1, $src2 \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region src1 src2 + // \ | | + // crx=cmpD_reg_reg + // + // with + // + // region src1 src2 + // \ | | + // crx=cmpDUnordered_reg_reg + // | + // ^ region + // | \ + // crx=cmov_bns_less + // + + // create new nodes + MachNode *m1 = new (C) cmpDUnordered_reg_regNode(); + MachNode *m2 = new (C) cmov_bns_lessNode(); + + // inputs for new nodes + m1->add_req(n_region, n_src1, n_src2); + m2->add_req(n_region); + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_crx; + m1->_opnds[1] = op_src1; + m1->_opnds[2] = op_src2; + m2->_opnds[0] = op_crx; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + +// Compare double, generate -1,0,1 +instruct cmpD3_reg_reg_ExEx(iRegIdst dst, regD src1, regD src2) %{ + match(Set dst (CmpD3 src1 src2)); + ins_cost(DEFAULT_COST*5+BRANCH_COST); + + expand %{ + flagsReg tmp1; + cmpDUnordered_reg_reg(tmp1, src1, src2); + cmovI_conIvalueMinus1_conIvalue0_conIvalue1_Ex(dst, tmp1); + %} +%} + +//----------Branches--------------------------------------------------------- +// Jump + +// Direct Branch. +instruct branch(label labl) %{ + match(Goto); + effect(USE labl); + ins_cost(BRANCH_COST); + + format %{ "B $labl" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_b); + Label d; // dummy + __ bind(d); + Label* p = $labl$$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); + __ b(l); + %} + ins_pipe(pipe_class_default); +%} + +// Conditional Near Branch +instruct branchCon(cmpOp cmp, flagsReg crx, label lbl) %{ + // Same match rule as `branchConFar'. + match(If cmp crx); + effect(USE lbl); + ins_cost(BRANCH_COST); + + // If set to 1 this indicates that the current instruction is a + // short variant of a long branch. This avoids using this + // instruction in first-pass matching. It will then only be used in + // the `Shorten_branches' pass. + ins_short_branch(1); + + format %{ "B$cmp $crx, $lbl" %} + size(4); + ins_encode( enc_bc(crx, cmp, lbl) ); + ins_pipe(pipe_class_default); +%} + +// This is for cases when the ppc64 `bc' instruction does not +// reach far enough. So we emit a far branch here, which is more +// expensive. +// +// Conditional Far Branch +instruct branchConFar(cmpOp cmp, flagsReg 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); + + // This is not a short variant of a branch, but the long variant. + ins_short_branch(0); + + format %{ "B_FAR$cmp $crx, $lbl" %} + size(8); + ins_encode( enc_bc_far(crx, cmp, lbl) ); + ins_pipe(pipe_class_default); +%} + +// Conditional Branch used with Power6 scheduler (can be far or short). +instruct branchConSched(cmpOp cmp, flagsReg 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, flagsReg crx, label labl) %{ + match(CountedLoopEnd cmp crx); + effect(USE labl); + ins_cost(BRANCH_COST); + + // short variant. + ins_short_branch(1); + + format %{ "B$cmp $crx, $labl \t// counted loop end" %} + size(4); + ins_encode( enc_bc(crx, cmp, labl) ); + ins_pipe(pipe_class_default); +%} + +instruct branchLoopEndFar(cmpOp cmp, flagsReg crx, label labl) %{ + match(CountedLoopEnd cmp crx); + effect(USE labl); + predicate(!false /* TODO: PPC port HB_Schedule */); + ins_cost(BRANCH_COST); + + // Long variant. + ins_short_branch(0); + + format %{ "B_FAR$cmp $crx, $labl \t// counted loop end" %} + size(8); + ins_encode( enc_bc_far(crx, cmp, labl) ); + ins_pipe(pipe_class_default); +%} + +// Conditional Branch used with Power6 scheduler (can be far or short). +instruct branchLoopEndSched(cmpOp cmp, flagsReg 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. + +// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass +// array for an instance of the superklass. Set a hidden internal cache on a +// hit (cache is checked with exposed code in gen_subtype_check()). Return +// not zero for a miss or zero for a hit. The encoding ALSO sets flags. +// +// GL TODO: Improve this. +// - result should not be a TEMP +// - Add match rule as on sparc avoiding additional Cmp. +instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P superklass, + iRegPdst tmp_klass, iRegPdst tmp_arrayptr) %{ + match(Set result (PartialSubtypeCheck subklass superklass)); + effect(TEMP result, TEMP tmp_klass, TEMP tmp_arrayptr); + ins_cost(DEFAULT_COST*10); + + 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); + %} + ins_pipe(pipe_class_default); +%} + +// inlined locking and unlocking + +instruct cmpFastLock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3) %{ + match(Set crx (FastLock oop box)); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3); + // TODO PPC port predicate(!UseNewFastLockPPC64 || UseBiasedLocking); + + format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2, $tmp3" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ compiler_fast_lock_object($crx$$CondRegister, $oop$$Register, $box$$Register, + $tmp3$$Register, $tmp1$$Register, $tmp2$$Register); + // If locking was successfull, crx should indicate 'EQ'. + // The compiler generates a branch to the runtime call to + // _complete_monitor_locking_Java for the case where crx is 'NE'. + %} + ins_pipe(pipe_class_compare); +%} + +instruct cmpFastUnlock(flagsReg crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3) %{ + match(Set crx (FastUnlock oop box)); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3); + + format %{ "FASTUNLOCK $oop, $box, $tmp1, $tmp2" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ compiler_fast_unlock_object($crx$$CondRegister, $oop$$Register, $box$$Register, + $tmp3$$Register, $tmp1$$Register, $tmp2$$Register); + // If unlocking was successfull, crx should indicate 'EQ'. + // The compiler generates a branch to the runtime call to + // _complete_monitor_unlocking_Java for the case where crx is 'NE'. + %} + ins_pipe(pipe_class_compare); +%} + +// Align address. +instruct align_addr(iRegPdst dst, iRegPsrc src, immLnegpow2 mask) %{ + match(Set dst (CastX2P (AndL (CastP2X src) 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); +%} + +// Array size computation. +instruct array_size(iRegLdst dst, iRegPsrc end, iRegPsrc start) %{ + match(Set dst (SubL (CastP2X end) (CastP2X 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); +%} + +// Clear-array with dynamic array-size. +instruct inlineCallClearArray(rarg1RegL cnt, rarg2RegP base, Universe dummy, regCTR ctr) %{ + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL cnt, USE_KILL base, KILL ctr); + ins_cost(MEMORY_REF_COST); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + format %{ "ClearArray $cnt, $base" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ clear_memory_doubleword($base$$Register, $cnt$$Register); // kills cnt, base, R0 + %} + ins_pipe(pipe_class_default); +%} + +// String_IndexOf for needle of length 1. +// +// Match needle into immediate operands: no loadConP node needed. Saves one +// register and two instructions over string_indexOf_imm1Node. +// +// Assumes register result differs from all input registers. +// +// Preserves registers haystack, haycnt +// Kills registers tmp1, tmp2 +// Defines registers result +// +// Use dst register classes if register gets killed, as it is the case for tmp registers! +// +// Unfortunately this does not match too often. In many situations the AddP is used +// by several nodes, even several StrIndexOf nodes, breaking the match tree. +instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + immP needleImm, immL offsetImm, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1) %{ + predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm))); + + effect(TEMP result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1); + + ins_cost(150); + format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]" + "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %} + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted + 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 * + + __ string_indexof_1($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, needle_values->char_at(0), + $tmp1$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +// String_IndexOf for needle of length 1. +// +// Special case requires less registers and emits less instructions. +// +// Assumes register result differs from all input registers. +// +// Preserves registers haystack, haycnt +// Kills registers tmp1, tmp2, needle +// Defines registers result +// +// Use dst register classes if register gets killed, as it is the case for tmp registers! +instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt, + rscratch2RegP needle, immI_1 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, + flagsRegCR0 cr0, flagsRegCR1 cr1) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL needle, /* TDEF needle, */ TEMP result, + TEMP tmp1, TEMP tmp2); + // Required for EA: check if it is still a type_array. + predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(180); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + 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"); + if (needle_values != NULL) { + __ string_indexof_1($result$$Register, + $haystack$$Register, $haycnt$$Register, + R0, needle_values->char_at(0), + $tmp1$$Register, $tmp2$$Register); + } else { + __ string_indexof_1($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, 0, + $tmp1$$Register, $tmp2$$Register); + } + %} + ins_pipe(pipe_class_compare); +%} + +// String_IndexOf. +// +// Length of needle as immediate. This saves instruction loading constant needle +// length. +// @@@ TODO Specify rules for length < 8 or so, and roll out comparison of needle +// completely or do it in vector instruction. This should save registers for +// needlecnt and needle. +// +// Assumes register result differs from all input registers. +// Overwrites haycnt, needlecnt. +// Use dst register classes if register gets killed, as it is the case for tmp registers! +instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, + iRegPsrc needle, uimmI15 needlecntImm, + iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm))); + effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6); + // Required for EA: check if it is still a type_array. + predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() && + n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array()); + ins_cost(250); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + 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(); + + __ string_indexof($result$$Register, + $haystack$$Register, $haycnt$$Register, + $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +// StrIndexOf node. +// +// Assumes register result differs from all input registers. +// Overwrites haycnt, needlecnt. +// Use dst register classes if register gets killed, as it is the case for tmp registers! +instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt, + iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{ + match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt))); + effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/ + TEMP result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6); + predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported. + ins_cost(300); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + 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. + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +// String equals with immediate. +instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIdst result, + iRegPdst tmp1, iRegPdst tmp2, + flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrEquals (Binary str1 str2) cntImm)); + effect(TEMP result, TEMP tmp1, TEMP tmp2, + KILL cr0, KILL cr6, KILL ctr); + predicate(SpecialStringEquals); // See Matcher::match_rule_supported. + ins_cost(250); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + format %{ "String Equals SCL [0..$cntImm]($str1),[0..$cntImm]($str2)" + " -> $result \t// KILL $cr0, $cr6, $ctr, TEMP $result, $tmp1, $tmp2" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ char_arrays_equalsImm($str1$$Register, $str2$$Register, $cntImm$$constant, + $result$$Register, $tmp1$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +// String equals. +// Use dst register classes if register gets killed, as it is the case for TEMP operands! +instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst result, + iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5, + flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{ + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, + KILL cr0, KILL cr1, KILL cr6, KILL ctr); + predicate(SpecialStringEquals); // See Matcher::match_rule_supported. + ins_cost(300); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + format %{ "String Equals [0..$cnt]($str1),[0..$cnt]($str2) -> $result" + " \t// KILL $cr0, $cr1, $cr6, $ctr, TEMP $result, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ char_arrays_equals($str1$$Register, $str2$$Register, $cnt$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +// String compare. +// Char[] pointers are passed in. +// Use dst register classes if register gets killed, as it is the case for TEMP operands! +instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result, + iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{ + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); + effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP result, TEMP tmp, KILL cr0, KILL ctr); + ins_cost(300); + + ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted. + + format %{ "String Compare $str1[0..$cnt1], $str2[0..$cnt2] -> $result" + " \t// TEMP $tmp, $result KILLs $str1, $cnt1, $str2, $cnt2, $cr0, $ctr" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, + $result$$Register, $tmp$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +//---------- Min/Max Instructions --------------------------------------------- + +instruct minI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (MinI src1 src2)); + ins_cost(DEFAULT_COST*6); + + expand %{ + iRegIdst src1s; + iRegIdst src2s; + iRegIdst diff; + iRegIdst sm; + iRegIdst doz; // difference or zero + sxtI_reg(src1s, src1); // Ensure proper sign extention. + sxtI_reg(src2s, src2); // Ensure proper sign extention. + subI_reg_reg(diff, src2s, src1s); + // Need to consider >=33 bit result, therefore we need signmaskL. + signmask64I_regI(sm, diff); + andI_reg_reg(doz, diff, sm); // <=0 + addI_reg_reg(dst, doz, src1s); + %} +%} + +instruct maxI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{ + match(Set dst (MaxI src1 src2)); + ins_cost(DEFAULT_COST*6); + + expand %{ + immI_minus1 m1 %{ -1 %} + iRegIdst src1s; + iRegIdst src2s; + iRegIdst diff; + iRegIdst sm; + iRegIdst doz; // difference or zero + sxtI_reg(src1s, src1); // Ensure proper sign extention. + sxtI_reg(src2s, src2); // Ensure proper sign extention. + subI_reg_reg(diff, src2s, src1s); + // Need to consider >=33 bit result, therefore we need signmaskL. + signmask64I_regI(sm, diff); + andcI_reg_reg(doz, sm, m1, diff); // >=0 + addI_reg_reg(dst, doz, src1s); + %} +%} + +//---------- Population Count Instructions ------------------------------------ + +// Popcnt for Power7. +instruct popCountI(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (PopCountI src)); + predicate(UsePopCountInstruction && VM_Version::has_popcntw()); + ins_cost(DEFAULT_COST); + + format %{ "POPCNTW $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_popcntb); + __ popcntw($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Popcnt for Power7. +instruct popCountL(iRegIdst dst, iRegLsrc src) %{ + predicate(UsePopCountInstruction && VM_Version::has_popcntw()); + match(Set dst (PopCountL src)); + ins_cost(DEFAULT_COST); + + format %{ "POPCNTD $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_popcntb); + __ popcntd($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct countLeadingZerosI(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (CountLeadingZerosI src)); + predicate(UseCountLeadingZerosInstructionsPPC64); // See Matcher::match_rule_supported. + ins_cost(DEFAULT_COST); + + format %{ "CNTLZW $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cntlzw); + __ cntlzw($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct countLeadingZerosL(iRegIdst dst, iRegLsrc src) %{ + match(Set dst (CountLeadingZerosL src)); + predicate(UseCountLeadingZerosInstructionsPPC64); // See Matcher::match_rule_supported. + ins_cost(DEFAULT_COST); + + format %{ "CNTLZD $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cntlzd); + __ cntlzd($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct countLeadingZerosP(iRegIdst dst, iRegPsrc src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + format %{ "CNTLZD $dst, $src" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cntlzd); + __ cntlzd($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct countTrailingZerosI_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (CountTrailingZerosI src)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI16 imm1 %{ (int)-1 %} + immI16 imm2 %{ (int)32 %} + immI_minus1 m1 %{ -1 %} + iRegIdst tmpI1; + iRegIdst tmpI2; + iRegIdst tmpI3; + addI_reg_imm16(tmpI1, src, imm1); + andcI_reg_reg(tmpI2, src, m1, tmpI1); + countLeadingZerosI(tmpI3, tmpI2); + subI_imm16_reg(dst, imm2, tmpI3); + %} +%} + +instruct countTrailingZerosL_Ex(iRegIdst dst, iRegLsrc src) %{ + match(Set dst (CountTrailingZerosL src)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immL16 imm1 %{ (long)-1 %} + immI16 imm2 %{ (int)64 %} + iRegLdst tmpL1; + iRegLdst tmpL2; + iRegIdst tmpL3; + addL_reg_imm16(tmpL1, src, imm1); + andcL_reg_reg(tmpL2, tmpL1, src); + countLeadingZerosL(tmpL3, tmpL2); + subI_imm16_reg(dst, imm2, tmpL3); + %} +%} + +// Expand nodes for byte_reverse_int. +instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ + effect(DEF dst, USE src, USE pos, USE shift); + predicate(false); + + 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); +%} + +// As insrwi_a, but with USE_DEF. +instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ + effect(USE_DEF dst, USE src, USE pos, USE shift); + predicate(false); + + 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); +%} + +// Just slightly faster than java implementation. +instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ReverseBytesI src)); + predicate(UseCountLeadingZerosInstructionsPPC64); + ins_cost(DEFAULT_COST); + + expand %{ + immI16 imm24 %{ (int) 24 %} + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + immI16 imm4 %{ (int) 4 %} + immI16 imm0 %{ (int) 0 %} + iRegLdst tmpI1; + iRegLdst tmpI2; + iRegLdst tmpI3; + + urShiftI_reg_imm(tmpI1, src, imm24); + insrwi_a(dst, tmpI1, imm24, imm8); + urShiftI_reg_imm(tmpI2, src, imm16); + insrwi(dst, tmpI2, imm8, imm16); + urShiftI_reg_imm(tmpI3, src, imm8); + insrwi(dst, tmpI3, imm8, imm8); + insrwi(dst, src, imm0, imm8); + %} +%} + +//---------- Replicate Vector Instructions ------------------------------------ + +// Insrdi does replicate if src == dst. +instruct repl32(iRegLdst dst) %{ + predicate(false); + effect(USE_DEF 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); +%} + +// Insrdi does replicate if src == dst. +instruct repl48(iRegLdst dst) %{ + predicate(false); + effect(USE_DEF 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); +%} + +// Insrdi does replicate if src == dst. +instruct repl56(iRegLdst dst) %{ + predicate(false); + effect(USE_DEF 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); +%} + +instruct repl8B_reg_Ex(iRegLdst dst, iRegIsrc src) %{ + match(Set dst (ReplicateB src)); + predicate(n->as_Vector()->length() == 8); + expand %{ + moveReg(dst, src); + repl56(dst); + repl48(dst); + repl32(dst); + %} +%} + +instruct repl8B_immI0(iRegLdst dst, immI_0 zero) %{ + match(Set dst (ReplicateB zero)); + predicate(n->as_Vector()->length() == 8); + 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); +%} + +instruct repl8B_immIminus1(iRegLdst dst, immI_minus1 src) %{ + match(Set dst (ReplicateB src)); + predicate(n->as_Vector()->length() == 8); + 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); +%} + +instruct repl4S_reg_Ex(iRegLdst dst, iRegIsrc src) %{ + match(Set dst (ReplicateS src)); + predicate(n->as_Vector()->length() == 4); + expand %{ + moveReg(dst, src); + repl48(dst); + repl32(dst); + %} +%} + +instruct repl4S_immI0(iRegLdst dst, immI_0 zero) %{ + match(Set dst (ReplicateS zero)); + predicate(n->as_Vector()->length() == 4); + format %{ "LI $dst, #0 \t// replicate4C" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ li($dst$$Register, (int)((short)($zero$$constant & 0xFFFF))); + %} + ins_pipe(pipe_class_default); +%} + +instruct repl4S_immIminus1(iRegLdst dst, immI_minus1 src) %{ + match(Set dst (ReplicateS src)); + predicate(n->as_Vector()->length() == 4); + format %{ "LI $dst, -1 \t// replicate4C" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); + %} + ins_pipe(pipe_class_default); +%} + +instruct repl2I_reg_Ex(iRegLdst dst, iRegIsrc src) %{ + match(Set dst (ReplicateI src)); + predicate(n->as_Vector()->length() == 2); + ins_cost(2 * DEFAULT_COST); + expand %{ + moveReg(dst, src); + repl32(dst); + %} +%} + +instruct repl2I_immI0(iRegLdst dst, immI_0 zero) %{ + match(Set dst (ReplicateI zero)); + predicate(n->as_Vector()->length() == 2); + format %{ "LI $dst, #0 \t// replicate4C" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ li($dst$$Register, (int)((short)($zero$$constant & 0xFFFF))); + %} + ins_pipe(pipe_class_default); +%} + +instruct repl2I_immIminus1(iRegLdst dst, immI_minus1 src) %{ + match(Set dst (ReplicateI src)); + predicate(n->as_Vector()->length() == 2); + format %{ "LI $dst, -1 \t// replicate4C" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ li($dst$$Register, (int)((short)($src$$constant & 0xFFFF))); + %} + ins_pipe(pipe_class_default); +%} + +// Move float to int register via stack, replicate. +instruct repl2F_reg_Ex(iRegLdst dst, regF src) %{ + match(Set dst (ReplicateF src)); + predicate(n->as_Vector()->length() == 2); + ins_cost(2 * MEMORY_REF_COST + DEFAULT_COST); + expand %{ + stackSlotL tmpS; + iRegIdst tmpI; + moveF2I_reg_stack(tmpS, src); // Move float to stack. + moveF2I_stack_reg(tmpI, tmpS); // Move stack to int reg. + moveReg(dst, tmpI); // Move int to long reg. + repl32(dst); // Replicate bitpattern. + %} +%} + +// Replicate scalar constant to packed float values in Double register +instruct repl2F_immF_Ex(iRegLdst dst, immF src) %{ + match(Set dst (ReplicateF src)); + predicate(n->as_Vector()->length() == 2); + ins_cost(5 * DEFAULT_COST); + + format %{ "LD $dst, offset, $constanttablebase\t// load replicated float $src $src from table, postalloc expanded" %} + postalloc_expand( postalloc_expand_load_replF_constant(dst, src, constanttablebase) ); +%} + +// Replicate scalar zero constant to packed float values in Double register +instruct repl2F_immF0(iRegLdst dst, immF_0 zero) %{ + match(Set dst (ReplicateF zero)); + predicate(n->as_Vector()->length() == 2); + + format %{ "LI $dst, #0 \t// replicate2F" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_addi); + __ li($dst$$Register, 0x0); + %} + ins_pipe(pipe_class_default); +%} + +// ============================================================================ +// Safepoint Instruction + +instruct safePoint_poll(iRegPdst poll) %{ + match(SafePoint poll); + predicate(LoadPollAddressFromThread); + + // It caused problems to add the effect that r0 is killed, but this + // effect no longer needs to be mentioned, since r0 is not contained + // in a reg_class. + + format %{ "LD R0, #0, $poll \t// Safepoint poll for GC" %} + size(4); + ins_encode( enc_poll(0x0, poll) ); + ins_pipe(pipe_class_default); +%} + +// Safepoint without per-thread support. Load address of page to poll +// as constant. +// Rscratch2RegP is R12. +// LoadConPollAddr node is added in pd_post_matching_hook(). It must be +// a seperate node so that the oop map is at the right location. +instruct safePoint_poll_conPollAddr(rscratch2RegP poll) %{ + match(SafePoint poll); + predicate(!LoadPollAddressFromThread); + + // It caused problems to add the effect that r0 is killed, but this + // effect no longer needs to be mentioned, since r0 is not contained + // in a reg_class. + + format %{ "LD R12, addr of polling page\n\t" + "LD R0, #0, R12 \t// Safepoint poll for GC" %} + ins_encode( enc_poll(0x0, poll) ); + ins_pipe(pipe_class_default); +%} + +// ============================================================================ +// Call Instructions + +// Call Java Static Instruction + +// Schedulable version of call static node. +instruct CallStaticJavaDirect(method meth) %{ + match(CallStaticJava); + effect(USE meth); + predicate(!((CallStaticJavaNode*)n)->is_method_handle_invoke()); + ins_cost(CALL_COST); + + ins_num_consts(3 /* up to 3 patchable constants: inline cache, 2 call targets. */); + + format %{ "CALL,static $meth \t// ==> " %} + size(4); + ins_encode( enc_java_static_call(meth) ); + ins_pipe(pipe_class_call); +%} + +// Schedulable version of call static node. +instruct CallStaticJavaDirectHandle(method meth) %{ + match(CallStaticJava); + effect(USE meth); + predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); + ins_cost(CALL_COST); + + ins_num_consts(3 /* up to 3 patchable constants: inline cache, 2 call targets. */); + + format %{ "CALL,static $meth \t// ==> " %} + ins_encode( enc_java_handle_call(meth) ); + ins_pipe(pipe_class_call); +%} + +// Call Java Dynamic Instruction + +// Used by postalloc expand of CallDynamicJavaDirectSchedEx (actual call). +// Loading of IC was postalloc expanded. The nodes loading the IC are reachable +// via fields ins_field_load_ic_hi_node and ins_field_load_ic_node. +// The call destination must still be placed in the constant pool. +instruct CallDynamicJavaDirectSched(method meth) %{ + match(CallDynamicJava); // To get all the data fields we need ... + effect(USE meth); + predicate(false); // ... but never match. + + ins_field_load_ic_hi_node(loadConL_hiNode*); + ins_field_load_ic_node(loadConLNode*); + ins_num_consts(1 /* 1 patchable constant: call destination */); + + format %{ "BL \t// dynamic $meth ==> " %} + size(4); + ins_encode( enc_java_dynamic_call_sched(meth) ); + ins_pipe(pipe_class_call); +%} + +// Schedulable (i.e. postalloc expanded) version of call dynamic java. +// We use postalloc expanded calls if we use inline caches +// and do not update method data. +// +// This instruction has two constants: inline cache (IC) and call destination. +// Loading the inline cache will be postalloc expanded, thus leaving a call with +// one constant. +instruct CallDynamicJavaDirectSched_Ex(method meth) %{ + match(CallDynamicJava); + effect(USE meth); + predicate(UseInlineCaches); + ins_cost(CALL_COST); + + ins_num_consts(2 /* 2 patchable constants: inline cache, call destination. */); + + format %{ "CALL,dynamic $meth \t// postalloc expanded" %} + postalloc_expand( postalloc_expand_java_dynamic_call_sched(meth, constanttablebase) ); +%} + +// Compound version of call dynamic java +// We use postalloc expanded calls if we use inline caches +// and do not update method data. +instruct CallDynamicJavaDirect(method meth) %{ + match(CallDynamicJava); + effect(USE meth); + predicate(!UseInlineCaches); + ins_cost(CALL_COST); + + // Enc_java_to_runtime_call needs up to 4 constants (method data oop). + ins_num_consts(4); + + format %{ "CALL,dynamic $meth \t// ==> " %} + ins_encode( enc_java_dynamic_call(meth, constanttablebase) ); + ins_pipe(pipe_class_call); +%} + +// Call Runtime Instruction + +instruct CallRuntimeDirect(method meth) %{ + match(CallRuntime); + effect(USE meth); + ins_cost(CALL_COST); + + // Enc_java_to_runtime_call needs up to 3 constants: call target, + // env for callee, C-toc. + ins_num_consts(3); + + format %{ "CALL,runtime" %} + ins_encode( enc_java_to_runtime_call(meth) ); + ins_pipe(pipe_class_call); +%} + +// Call Leaf + +// Used by postalloc expand of CallLeafDirect_Ex (mtctr). +instruct CallLeafDirect_mtctr(iRegLdst dst, iRegLsrc src) %{ + effect(DEF dst, USE src); + + ins_num_consts(1); + + format %{ "MTCTR $src" %} + size(4); + ins_encode( enc_leaf_call_mtctr(src) ); + ins_pipe(pipe_class_default); +%} + +// Used by postalloc expand of CallLeafDirect_Ex (actual call). +instruct CallLeafDirect(method meth) %{ + match(CallLeaf); // To get the data all the data fields we need ... + effect(USE meth); + predicate(false); // but never match. + + format %{ "BCTRL \t// leaf call $meth ==> " %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_bctrl); + __ bctrl(); + %} + ins_pipe(pipe_class_call); +%} + +// postalloc expand of CallLeafDirect. +// Load adress to call from TOC, then bl to it. +instruct CallLeafDirect_Ex(method meth) %{ + match(CallLeaf); + effect(USE meth); + ins_cost(CALL_COST); + + // Postalloc_expand_java_to_runtime_call needs up to 3 constants: call target, + // env for callee, C-toc. + ins_num_consts(3); + + format %{ "CALL,runtime leaf $meth \t// postalloc expanded" %} + postalloc_expand( postalloc_expand_java_to_runtime_call(meth, constanttablebase) ); +%} + +// Call runtime without safepoint - same as CallLeaf. +// postalloc expand of CallLeafNoFPDirect. +// Load adress to call from TOC, then bl to it. +instruct CallLeafNoFPDirect_Ex(method meth) %{ + match(CallLeafNoFP); + effect(USE meth); + ins_cost(CALL_COST); + + // Enc_java_to_runtime_call needs up to 3 constants: call target, + // env for callee, C-toc. + ins_num_consts(3); + + format %{ "CALL,runtime leaf nofp $meth \t// postalloc expanded" %} + postalloc_expand( postalloc_expand_java_to_runtime_call(meth, constanttablebase) ); +%} + +// Tail Call; Jump from runtime stub to Java code. +// Also known as an 'interprocedural jump'. +// Target of jump will eventually return to caller. +// TailJump below removes the return address. +instruct TailCalljmpInd(iRegPdstNoScratch jump_target, inline_cache_regP method_oop) %{ + match(TailCall jump_target method_oop); + ins_cost(CALL_COST); + + format %{ "MTCTR $jump_target \t// $method_oop holds method oop\n\t" + "BCTR \t// tail call" %} + size(8); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_compound); + __ mtctr($jump_target$$Register); + __ bctr(); + %} + ins_pipe(pipe_class_call); +%} + +// Return Instruction +instruct Ret() %{ + match(Return); + 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(); + %} + ins_pipe(pipe_class_default); +%} + +// Tail Jump; remove the return address; jump to target. +// TailCall above leaves the return address around. +// TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). +// ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a +// "restore" before this instruction (in Epilogue), we need to materialize it +// in %i0. +instruct tailjmpInd(iRegPdstNoScratch jump_target, rarg1RegP ex_oop) %{ + match(TailJump jump_target ex_oop); + ins_cost(CALL_COST); + + format %{ "LD R4_ARG2 = LR\n\t" + "MTCTR $jump_target\n\t" + "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(); + %} + ins_pipe(pipe_class_call); +%} + +// Create exception oop: created by stack-crawling runtime code. +// Created exception is now available to this handler, and is setup +// just prior to jumping to this handler. No code emitted. +instruct CreateException(rarg1RegP ex_oop) %{ + match(Set ex_oop (CreateEx)); + ins_cost(0); + + format %{ " -- \t// exception oop; no code emitted" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_default); +%} + +// Rethrow exception: The exception oop will come in the first +// argument position. Then JUMP (not call) to the rethrow stub code. +instruct RethrowException() %{ + match(Rethrow); + ins_cost(CALL_COST); + + 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); + %} + ins_pipe(pipe_class_call); +%} + +// Die now. +instruct ShouldNotReachHere() %{ + match(Halt); + ins_cost(CALL_COST); + + format %{ "ShouldNotReachHere" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_tdi); + __ trap_should_not_reach_here(); + %} + ins_pipe(pipe_class_default); +%} + +// This name is KNOWN by the ADLC and cannot be changed. The ADLC +// forces a 'TypeRawPtr::BOTTOM' output type for this guy. +// Get a DEF on threadRegP, no costs, no encoding, use +// 'ins_should_rematerialize(true)' to avoid spilling. +instruct tlsLoadP(threadRegP dst) %{ + match(Set dst (ThreadLocal)); + ins_cost(0); + + ins_should_rematerialize(true); + + format %{ " -- \t// $dst=Thread::current(), empty" %} + size(0); + ins_encode( /*empty*/ ); + ins_pipe(pipe_class_empty); +%} + +//---Some PPC specific nodes--------------------------------------------------- + +// Stop a group. +instruct endGroup() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "End Bundle (ori r1, r1, 0)" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_endgroup); + __ endgroup(); + %} + ins_pipe(pipe_class_default); +%} + +// Nop instructions + +instruct fxNop() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "fxNop" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_fmr); + __ nop(); + %} + ins_pipe(pipe_class_default); +%} + +instruct fpNop0() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "fpNop0" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_fmr); + __ fpnop0(); + %} + ins_pipe(pipe_class_default); +%} + +instruct fpNop1() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "fpNop1" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_fmr); + __ fpnop1(); + %} + ins_pipe(pipe_class_default); +%} + +instruct brNop0() %{ + ins_cost(0); + size(4); + format %{ "brNop0" %} + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); + __ brnop0(); + %} + ins_is_nop(true); + ins_pipe(pipe_class_default); +%} + +instruct brNop1() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "brNop1" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); + __ brnop1(); + %} + ins_pipe(pipe_class_default); +%} + +instruct brNop2() %{ + ins_cost(0); + + ins_is_nop(true); + + format %{ "brNop2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_mcrf); + __ brnop2(); + %} + ins_pipe(pipe_class_default); +%} + +//----------PEEPHOLE RULES----------------------------------------------------- +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. +// +// peepmatch ( root_instr_name [preceeding_instruction]* ); +// +// peepconstraint %{ +// (instruction_number.operand_name relational_op instruction_number.operand_name +// [, ...] ); +// // instruction numbers are zero-based using left to right order in peepmatch +// +// peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); +// // provide an instruction_number.operand_name for each operand that appears +// // in the replacement instruction's match rule +// +// ---------VM FLAGS--------------------------------------------------------- +// +// All peephole optimizations can be turned off using -XX:-OptoPeephole +// +// Each peephole rule is given an identifying number starting with zero and +// increasing by one in the order seen by the parser. An individual peephole +// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# +// on the command-line. +// +// ---------CURRENT LIMITATIONS---------------------------------------------- +// +// Only match adjacent instructions in same basic block +// Only equality constraints +// Only constraints between operands, not (0.dest_reg == EAX_enc) +// Only one replacement instruction +// +// ---------EXAMPLE---------------------------------------------------------- +// +// // pertinent parts of existing instructions in architecture description +// instruct movI(eRegI dst, eRegI src) %{ +// match(Set dst (CopyI src)); +// %} +// +// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ +// match(Set dst (AddI dst src)); +// effect(KILL cr); +// %} +// +// // Change (inc mov) to lea +// peephole %{ +// // increment preceeded by register-register move +// peepmatch ( incI_eReg movI ); +// // require that the destination register of the increment +// // match the destination register of the move +// peepconstraint ( 0.dst == 1.dst ); +// // construct a replacement instruction that sets +// // the destination to ( move's source register + one ) +// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) ); +// %} +// +// Implementation no longer uses movX instructions since +// machine-independent system no longer uses CopyX nodes. +// +// peephole %{ +// peepmatch ( incI_eReg movI ); +// peepconstraint ( 0.dst == 1.dst ); +// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) ); +// %} +// +// peephole %{ +// peepmatch ( decI_eReg movI ); +// peepconstraint ( 0.dst == 1.dst ); +// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) ); +// %} +// +// peephole %{ +// peepmatch ( addI_eReg_imm movI ); +// peepconstraint ( 0.dst == 1.dst ); +// peepreplace ( leaI_eReg_immI( 0.dst 1.src 0.src ) ); +// %} +// +// peephole %{ +// peepmatch ( addP_eReg_imm movP ); +// peepconstraint ( 0.dst == 1.dst ); +// peepreplace ( leaP_eReg_immI( 0.dst 1.src 0.src ) ); +// %} + +// // Change load of spilled value to only a spill +// instruct storeI(memory mem, eRegI src) %{ +// match(Set mem (StoreI mem src)); +// %} +// +// instruct loadI(eRegI dst, memory mem) %{ +// match(Set dst (LoadI mem)); +// %} +// +peephole %{ + peepmatch ( loadI storeI ); + peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); + peepreplace ( storeI( 1.mem 1.mem 1.src ) ); +%} + +peephole %{ + peepmatch ( loadL storeL ); + peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); + peepreplace ( storeL( 1.mem 1.mem 1.src ) ); +%} + +peephole %{ + peepmatch ( loadP storeP ); + peepconstraint ( 1.src == 0.dst, 1.dst == 0.mem ); + peepreplace ( storeP( 1.dst 1.dst 1.src ) ); +%} + +//----------SMARTSPILL RULES--------------------------------------------------- +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. diff --git a/hotspot/src/cpu/ppc/vm/ppc_64.ad b/hotspot/src/cpu/ppc/vm/ppc_64.ad new file mode 100644 index 00000000000..4c1be69601a --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/ppc_64.ad @@ -0,0 +1,24 @@ +// +// Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright 2012, 2013 SAP AG. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// diff --git a/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp b/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp index d5d41811dfb..a009ea06f77 100644 --- a/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/register_definitions_ppc.cpp @@ -30,8 +30,8 @@ #include "asm/macroAssembler.hpp" #include "asm/register.hpp" #include "register_ppc.hpp" -#ifdef TARGET_ARCH_MODEL_32 -# include "interp_masm_32.hpp" +#ifdef TARGET_ARCH_MODEL_ppc_32 +# include "interp_masm_ppc_32.hpp" #endif #ifdef TARGET_ARCH_MODEL_ppc_64 # include "interp_masm_ppc_64.hpp" diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.cpp b/hotspot/src/cpu/ppc/vm/register_ppc.cpp index 5054be245c5..edff7485a97 100644 --- a/hotspot/src/cpu/ppc/vm/register_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/register_ppc.cpp @@ -44,7 +44,7 @@ const char* RegisterImpl::name() const { const char* ConditionRegisterImpl::name() const { const char* names[number_of_registers] = { - "CR0", "CR1", "CR2", "CR3", "CCR4", "CCR5", "CCR6", "CCR7" + "CR0", "CR1", "CR2", "CR3", "CR4", "CR5", "CR6", "CR7" }; return is_valid() ? names[encoding()] : "cnoreg"; } @@ -61,7 +61,7 @@ const char* FloatRegisterImpl::name() const { const char* SpecialRegisterImpl::name() const { const char* names[number_of_registers] = { - "SR_XER", "SR_LR", "SR_CTR", "SR_VRSAVE", "R1_SPEFSCR", "SR_PPR" + "SR_XER", "SR_LR", "SR_CTR", "SR_VRSAVE", "SR_SPEFSCR", "SR_PPR" }; return is_valid() ? names[encoding()] : "snoreg"; } diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.hpp b/hotspot/src/cpu/ppc/vm/register_ppc.hpp index 66130f9f2c5..bc04d8d2c16 100644 --- a/hotspot/src/cpu/ppc/vm/register_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/register_ppc.hpp @@ -60,8 +60,8 @@ typedef VMRegImpl* VMReg; // FPSCR Floating point status and control register (volatile) // // CR0-CR1 Condition code fields (volatile) -// CR2-CCR4 Condition code fields (nonvolatile) -// CCR5-CCR7 Condition code fields (volatile) +// CR2-CR4 Condition code fields (nonvolatile) +// CR5-CR7 Condition code fields (volatile) // // ---------------------------------------------- // On processors with the VMX feature: @@ -531,7 +531,7 @@ REGISTER_DECLARATION(Register, R7_ARG5, R7); // volatile REGISTER_DECLARATION(Register, R8_ARG6, R8); // volatile REGISTER_DECLARATION(Register, R9_ARG7, R9); // volatile REGISTER_DECLARATION(Register, R10_ARG8, R10); // volatile -REGISTER_DECLARATION(FloatRegister, FO_SCRATCH, F0); // volatile +REGISTER_DECLARATION(FloatRegister, F0_SCRATCH, F0); // volatile REGISTER_DECLARATION(FloatRegister, F1_RET, F1); // volatile REGISTER_DECLARATION(FloatRegister, F1_ARG1, F1); // volatile REGISTER_DECLARATION(FloatRegister, F2_ARG2, F2); // volatile @@ -560,7 +560,7 @@ REGISTER_DECLARATION(FloatRegister, F13_ARG13, F13); // volatile #define R8_ARG6 AS_REGISTER(Register, R8) #define R9_ARG7 AS_REGISTER(Register, R9) #define R10_ARG8 AS_REGISTER(Register, R10) -#define FO_SCRATCH AS_REGISTER(FloatRegister, F0) +#define F0_SCRATCH AS_REGISTER(FloatRegister, F0) #define F1_RET AS_REGISTER(FloatRegister, F1) #define F1_ARG1 AS_REGISTER(FloatRegister, F1) #define F2_ARG2 AS_REGISTER(FloatRegister, F2) @@ -608,7 +608,6 @@ REGISTER_DECLARATION(Register, R26_tmp6, R26); REGISTER_DECLARATION(Register, R27_tmp7, R27); REGISTER_DECLARATION(Register, R28_tmp8, R28); REGISTER_DECLARATION(Register, R29_tmp9, R29); -REGISTER_DECLARATION(Register, R30_polling_page, R30); #ifndef DONT_USE_REGISTER_DEFINES #define R21_tmp1 AS_REGISTER(Register, R21) #define R22_tmp2 AS_REGISTER(Register, R22) @@ -619,7 +618,6 @@ REGISTER_DECLARATION(Register, R30_polling_page, R30); #define R27_tmp7 AS_REGISTER(Register, R27) #define R28_tmp8 AS_REGISTER(Register, R28) #define R29_tmp9 AS_REGISTER(Register, R29) -#define R30_polling_page AS_REGISTER(Register, R30) #define CCR4_is_synced AS_REGISTER(ConditionRegister, CCR4) #endif diff --git a/hotspot/src/cpu/ppc/vm/runtime_ppc.cpp b/hotspot/src/cpu/ppc/vm/runtime_ppc.cpp new file mode 100644 index 00000000000..bc3432bb1e3 --- /dev/null +++ b/hotspot/src/cpu/ppc/vm/runtime_ppc.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2013 SAP AG. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#ifdef COMPILER2 +#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "classfile/systemDictionary.hpp" +#include "code/vmreg.hpp" +#include "interpreter/interpreter.hpp" +#include "nativeInst_ppc.hpp" +#include "opto/runtime.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/globalDefinitions.hpp" +#include "vmreg_ppc.inline.hpp" +#endif + +#define __ masm-> + + +#ifdef COMPILER2 + +// SP adjustment (must use unextended SP) for method handle call sites +// during exception handling. +static intptr_t adjust_SP_for_methodhandle_callsite(JavaThread *thread) { + RegisterMap map(thread, false); + // The frame constructor will do the correction for us (see frame::adjust_unextended_SP). + frame mh_caller_frame = thread->last_frame().sender(&map); + assert(mh_caller_frame.is_compiled_frame(), "Only may reach here for compiled MH call sites"); + return (intptr_t) mh_caller_frame.unextended_sp(); +} + +//------------------------------generate_exception_blob--------------------------- +// Creates exception blob at the end. +// Using exception blob, this code is jumped from a compiled method. +// +// Given an exception pc at a call we call into the runtime for the +// handler in this method. This handler might merely restore state +// (i.e. callee save registers) unwind the frame and jump to the +// exception handler for the nmethod if there is no Java level handler +// for the nmethod. +// +// This code is entered with a jmp. +// +// Arguments: +// R3_ARG1: exception oop +// R4_ARG2: exception pc +// +// Results: +// R3_ARG1: exception oop +// R4_ARG2: exception pc in caller +// destination: exception handler of caller +// +// Note: the exception pc MUST be at a call (precise debug information) +// +void OptoRuntime::generate_exception_blob() { + // Allocate space for the code. + ResourceMark rm; + // Setup code generation tools. + CodeBuffer buffer("exception_blob", 2048, 1024); + InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer); + + address start = __ pc(); + + int frame_size_in_bytes = frame::abi_112_size; + OopMap* map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); + + // Exception pc is 'return address' for stack walker. + __ std(R4_ARG2/*exception pc*/, _abi(lr), R1_SP); + + // Store the exception in the Thread object. + __ std(R3_ARG1/*exception oop*/, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + __ std(R4_ARG2/*exception pc*/, in_bytes(JavaThread::exception_pc_offset()), R16_thread); + + // Save callee-saved registers. + // Push a C frame for the exception blob. It is needed for the C call later on. + __ push_frame_abi112(0, R11_scratch1); + + // This call does all the hard work. It checks if an exception handler + // exists in the method. + // If so, it returns the handler address. + // If not, it prepares for stack-unwinding, restoring the callee-save + // registers of the frame being removed. + __ set_last_Java_frame(/*sp=*/R1_SP, noreg); + + __ mr(R3_ARG1, R16_thread); + __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, OptoRuntime::handle_exception_C), + relocInfo::none); + address calls_return_pc = __ last_calls_return_pc(); +# ifdef ASSERT + __ cmpdi(CCR0, R3_RET, 0); + __ asm_assert_ne("handle_exception_C must not return NULL", 0x601); +# endif + + // Set an oopmap for the call site. This oopmap will only be used if we + // are unwinding the stack. Hence, all locations will be dead. + // Callee-saved registers will be the same as the frame above (i.e., + // handle_exception_stub), since they were restored when we got the + // exception. + OopMapSet* oop_maps = new OopMapSet(); + oop_maps->add_gc_map(calls_return_pc - start, map); + + // Get unextended_sp for method handle call sites. + Label mh_callsite, mh_done; // Use a 2nd c call if it's a method handle call site. + __ lwa(R4_ARG2, in_bytes(JavaThread::is_method_handle_return_offset()), R16_thread); + __ cmpwi(CCR0, R4_ARG2, 0); + __ bne(CCR0, mh_callsite); + + __ mtctr(R3_RET); // Move address of exception handler to SR_CTR. + __ reset_last_Java_frame(); + __ pop_frame(); + + __ bind(mh_done); + // We have a handler in register SR_CTR (could be deopt blob). + + // Get the exception oop. + __ ld(R3_ARG1, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + + // Get the exception pc in case we are deoptimized. + __ ld(R4_ARG2, in_bytes(JavaThread::exception_pc_offset()), R16_thread); + + // Reset thread values. + __ li(R0, 0); +#ifdef ASSERT + __ std(R0, in_bytes(JavaThread::exception_handler_pc_offset()), R16_thread); + __ std(R0, in_bytes(JavaThread::exception_pc_offset()), R16_thread); +#endif + // Clear the exception oop so GC no longer processes it as a root. + __ std(R0, in_bytes(JavaThread::exception_oop_offset()), R16_thread); + + // Move exception pc into SR_LR. + __ mtlr(R4_ARG2); + __ bctr(); + + + // Same as above, but also set sp to unextended_sp. + __ bind(mh_callsite); + __ mr(R31, R3_RET); // Save branch address. + __ mr(R3_ARG1, R16_thread); + __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, adjust_SP_for_methodhandle_callsite), relocInfo::none); + // Returns unextended_sp in R3_RET. + + __ mtctr(R31); // Move address of exception handler to SR_CTR. + __ reset_last_Java_frame(); + + __ mr(R1_SP, R3_RET); // Set sp to unextended_sp. + __ b(mh_done); + + + // Make sure all code is generated. + masm->flush(); + + // Set exception blob. + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, + frame_size_in_bytes/wordSize); +} + +#endif // COMPILER2 diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index c2a971118cf..2d9b4900bce 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -687,17 +687,9 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, F13->as_VMReg() }; - const int num_iarg_registers = sizeof(iarg_reg) / sizeof(iarg_reg[0]); - const int num_farg_registers = sizeof(farg_reg) / sizeof(farg_reg[0]); - - // The first 8 arguments are not passed on the stack. - const int num_args_in_regs = 8; -#define put_arg_in_reg(arg) ((arg) < num_args_in_regs) - // Check calling conventions consistency. - assert(num_iarg_registers == num_args_in_regs - && num_iarg_registers == 8 - && num_farg_registers == 13, + assert(sizeof(iarg_reg) / sizeof(iarg_reg[0]) == Argument::n_int_register_parameters_c && + sizeof(farg_reg) / sizeof(farg_reg[0]) == Argument::n_float_register_parameters_c, "consistency"); // `Stk' counts stack slots. Due to alignment, 32 bit values occupy @@ -705,8 +697,6 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, const int inc_stk_for_intfloat = 2; // 2 slots for ints and floats const int inc_stk_for_longdouble = 2; // 2 slots for longs and doubles - int ill_i = 0; - int ill_t = 0; int i; VMReg reg; // Leave room for C-compatible ABI_112. @@ -726,6 +716,11 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, if (regs2 != NULL) regs2[i].set_bad(); switch(sig_bt[i]) { + + // + // If arguments 0-7 are integers, they are passed in integer registers. + // Argument i is placed in iarg_reg[i]. + // case T_BOOLEAN: case T_CHAR: case T_BYTE: @@ -754,7 +749,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, case T_ADDRESS: case T_METADATA: // Oops are already boxed if required (JNI). - if (put_arg_in_reg(arg)) { + if (arg < Argument::n_int_register_parameters_c) { reg = iarg_reg[arg]; } else { reg = VMRegImpl::stack2reg(stk); @@ -762,57 +757,66 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, } regs[i].set2(reg); break; + + // + // Floats are treated differently from int regs: The first 13 float arguments + // are passed in registers (not the float args among the first 13 args). + // Thus argument i is NOT passed in farg_reg[i] if it is float. It is passed + // in farg_reg[j] if argument i is the j-th float argument of this call. + // case T_FLOAT: - if (put_arg_in_reg(arg)) { + if (freg < Argument::n_float_register_parameters_c) { + // Put float in register ... reg = farg_reg[freg]; + ++freg; + + // Argument i for i > 8 is placed on the stack even if it's + // placed in a register (if it's a float arg). Aix disassembly + // shows that xlC places these float args on the stack AND in + // a register. This is not documented, but we follow this + // convention, too. + if (arg >= Argument::n_regs_not_on_stack_c) { + // ... and on the stack. + guarantee(regs2 != NULL, "must pass float in register and stack slot"); + VMReg reg2 = VMRegImpl::stack2reg(stk LINUX_ONLY(+1)); + regs2[i].set1(reg2); + stk += inc_stk_for_intfloat; + } + } else { - // Put float on stack -# if defined(LINUX) - reg = VMRegImpl::stack2reg(stk+1); -# elif defined(AIX) - reg = VMRegImpl::stack2reg(stk); -# else -# error "unknown OS" -# endif + // Put float on stack. + reg = VMRegImpl::stack2reg(stk LINUX_ONLY(+1)); stk += inc_stk_for_intfloat; } - - if (freg < num_farg_registers) { - // There are still some float argument registers left. Put the - // float in a register if not already done. - if (reg != farg_reg[freg]) { - guarantee(regs2 != NULL, "must pass float in register and stack slot"); - VMReg reg2 = farg_reg[freg]; - regs2[i].set1(reg2); - } - ++freg; - } - regs[i].set1(reg); break; case T_DOUBLE: assert(sig_bt[i+1] == T_VOID, "expecting half"); - if (put_arg_in_reg(arg)) { + if (freg < Argument::n_float_register_parameters_c) { + // Put double in register ... reg = farg_reg[freg]; + ++freg; + + // Argument i for i > 8 is placed on the stack even if it's + // placed in a register (if it's a double arg). Aix disassembly + // shows that xlC places these float args on the stack AND in + // a register. This is not documented, but we follow this + // convention, too. + if (arg >= Argument::n_regs_not_on_stack_c) { + // ... and on the stack. + guarantee(regs2 != NULL, "must pass float in register and stack slot"); + VMReg reg2 = VMRegImpl::stack2reg(stk); + regs2[i].set2(reg2); + stk += inc_stk_for_longdouble; + } } else { // Put double on stack. reg = VMRegImpl::stack2reg(stk); stk += inc_stk_for_longdouble; } - - if (freg < num_farg_registers) { - // There are still some float argument registers left. Put the - // float in a register if not already done. - if (reg != farg_reg[freg]) { - guarantee(regs2 != NULL, "must pass float in register and stack slot"); - VMReg reg2 = farg_reg[freg]; - regs2[i].set2(reg2); - } - ++freg; - } - regs[i].set2(reg); break; + case T_VOID: // Do not count halves. regs[i].set_bad(); @@ -877,7 +881,7 @@ static address gen_c2i_adapter(MacroAssembler *masm, __ mtlr(return_pc); - // call the interpreter + // Call the interpreter. __ BIND(call_interpreter); __ mtctr(ientry); @@ -947,8 +951,12 @@ static address gen_c2i_adapter(MacroAssembler *masm, // Jump to the interpreter just as if interpreter was doing it. +#ifdef CC_INTERP + const Register tos = R17_tos; +#endif + // load TOS - __ addi(R17_tos, R1_SP, st_off); + __ addi(tos, R1_SP, st_off); // Frame_manager expects initial_caller_sp (= SP without resize by c2i) in R21_tmp1. assert(sender_SP == R21_sender_SP, "passing initial caller's SP in wrong register"); @@ -982,7 +990,9 @@ static void gen_i2c_adapter(MacroAssembler *masm, // save code can segv when fxsave instructions find improperly // aligned stack pointer. +#ifdef CC_INTERP const Register ld_ptr = R17_tos; +#endif const Register value_regs[] = { R22_tmp2, R23_tmp3, R24_tmp4, R25_tmp5, R26_tmp6 }; const int num_value_regs = sizeof(value_regs) / sizeof(Register); int value_regs_index = 0; @@ -1137,7 +1147,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm __ bne_predict_taken(CCR0, valid); // We have a null argument, branch to ic_miss_stub. __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); + relocInfo::runtime_call_type); __ BIND(valid); } } @@ -1154,7 +1164,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm __ beq_predict_taken(CCR0, valid); // We have an unexpected klass, branch to ic_miss_stub. __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); + relocInfo::runtime_call_type); __ BIND(valid); } @@ -1170,8 +1180,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm __ beq_predict_taken(CCR0, call_interpreter); // Branch to ic_miss_stub. - __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), - relocInfo::runtime_call_type); + __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); // entry: c2i @@ -2594,7 +2603,11 @@ static void push_skeleton_frame(MacroAssembler* masm, bool deopt, __ ld(frame_size_reg, 0, frame_sizes_reg); __ std(pc_reg, _abi(lr), R1_SP); __ push_frame(frame_size_reg, R0/*tmp*/); +#ifdef CC_INTERP __ std(R1_SP, _parent_ijava_frame_abi(initial_caller_sp), R1_SP); +#else + Unimplemented(); +#endif __ addi(number_of_frames_reg, number_of_frames_reg, -1); __ addi(frame_sizes_reg, frame_sizes_reg, wordSize); __ addi(pcs_reg, pcs_reg, wordSize); @@ -2693,7 +2706,9 @@ static void push_skeleton_frames(MacroAssembler* masm, bool deopt, // Store it in the top interpreter frame. __ std(R0, _abi(lr), R1_SP); // Initialize frame_manager_lr of interpreter top frame. +#ifdef CC_INTERP __ std(R0, _top_ijava_frame_abi(frame_manager_lr), R1_SP); +#endif } #endif @@ -2886,8 +2901,7 @@ void SharedRuntime::generate_deopt_blob() { // Initialize R14_state. __ ld(R14_state, 0, R1_SP); - __ addi(R14_state, R14_state, - -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + __ addi(R14_state, R14_state, -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); // Also inititialize R15_prev_state. __ restore_prev_state(); @@ -3010,8 +3024,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { // Initialize R14_state, ... __ ld(R11_scratch1, 0, R1_SP); - __ addi(R14_state, R11_scratch1, - -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); + __ addi(R14_state, R11_scratch1, -frame::interpreter_frame_cinterpreterstate_size_in_bytes()); // also initialize R15_prev_state. __ restore_prev_state(); // Return to the interpreter entry point. diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index d5f8be7c4bd..c9a4538454a 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -146,14 +146,14 @@ class StubGenerator: public StubCodeGenerator { // FIXME: use round_to() here __ andi_(r_frame_alignment_in_bytes, r_arg_argument_count, 1); __ sldi(r_frame_alignment_in_bytes, - r_frame_alignment_in_bytes, Interpreter::logStackElementSize); + r_frame_alignment_in_bytes, Interpreter::logStackElementSize); // size = unaligned size of arguments + top abi's size __ addi(r_frame_size, r_argument_size_in_bytes, frame::top_ijava_frame_abi_size); // size += arguments alignment __ add(r_frame_size, - r_frame_size, r_frame_alignment_in_bytes); + r_frame_size, r_frame_alignment_in_bytes); // size += size of call_stub locals __ addi(r_frame_size, r_frame_size, frame::entry_frame_locals_size); @@ -179,7 +179,7 @@ class StubGenerator: public StubCodeGenerator { __ addi(r_top_of_arguments_addr, R1_SP, frame::top_ijava_frame_abi_size); __ add(r_top_of_arguments_addr, - r_top_of_arguments_addr, r_frame_alignment_in_bytes); + r_top_of_arguments_addr, r_frame_alignment_in_bytes); // any arguments to copy? __ cmpdi(CCR0, r_arg_argument_count, 0); @@ -229,22 +229,23 @@ class StubGenerator: public StubCodeGenerator { // Register state on entry to frame manager / native entry: // - // R17_tos - intptr_t* sender tos (prepushed) Lesp = (SP) + copied_arguments_offset - 8 + // tos - intptr_t* sender tos (prepushed) Lesp = (SP) + copied_arguments_offset - 8 // R19_method - Method // R16_thread - JavaThread* - // R17_tos must point to last argument - element_size. - __ addi(R17_tos, r_top_of_arguments_addr, -Interpreter::stackElementSize); + // Tos must point to last argument - element_size. + const Register tos = R17_tos; + __ addi(tos, r_top_of_arguments_addr, -Interpreter::stackElementSize); // initialize call_stub locals (step 2) - // now save R17_tos as arguments_tos_address - __ std(R17_tos, _entry_frame_locals_neg(arguments_tos_address), r_entryframe_fp); + // now save tos as arguments_tos_address + __ std(tos, _entry_frame_locals_neg(arguments_tos_address), r_entryframe_fp); // load argument registers for call __ mr(R19_method, r_arg_method); __ mr(R16_thread, r_arg_thread); - assert(R17_tos != r_arg_method, "trashed r_arg_method"); - assert(R17_tos != r_arg_thread && R19_method != r_arg_thread, "trashed r_arg_thread"); + assert(tos != r_arg_method, "trashed r_arg_method"); + assert(tos != r_arg_thread && R19_method != r_arg_thread, "trashed r_arg_thread"); // Set R15_prev_state to 0 for simplifying checks in callee. __ li(R15_prev_state, 0); @@ -274,7 +275,7 @@ class StubGenerator: public StubCodeGenerator { // Do a light-weight C-call here, r_new_arg_entry holds the address // of the interpreter entry point (frame manager or native entry) // and save runtime-value of LR in return_address. - assert(r_new_arg_entry != R17_tos && r_new_arg_entry != R19_method && r_new_arg_entry != R16_thread, + assert(r_new_arg_entry != tos && r_new_arg_entry != R19_method && r_new_arg_entry != R16_thread, "trashed r_new_arg_entry"); return_address = __ call_stub(r_new_arg_entry); } @@ -326,8 +327,8 @@ class StubGenerator: public StubCodeGenerator { // T_OBJECT, T_LONG, T_FLOAT, or T_DOUBLE is treated as T_INT. __ cmpwi(CCR0, r_arg_result_type, T_OBJECT); __ cmpwi(CCR1, r_arg_result_type, T_LONG); - __ cmpwi(CCR5, r_arg_result_type, T_FLOAT); - __ cmpwi(CCR6, r_arg_result_type, T_DOUBLE); + __ cmpwi(CCR5, r_arg_result_type, T_FLOAT); + __ cmpwi(CCR6, r_arg_result_type, T_DOUBLE); // restore non-volatile registers __ restore_nonvolatile_gprs(R1_SP, _spill_nonvolatiles_neg(r14)); @@ -345,8 +346,8 @@ class StubGenerator: public StubCodeGenerator { __ beq(CCR0, ret_is_object); __ beq(CCR1, ret_is_long); - __ beq(CCR5, ret_is_float); - __ beq(CCR6, ret_is_double); + __ beq(CCR5, ret_is_float); + __ beq(CCR6, ret_is_double); // default: __ stw(R3_RET, 0, r_arg_result_addr); @@ -614,6 +615,17 @@ class StubGenerator: public StubCodeGenerator { if (!dest_uninitialized) { const int spill_slots = 4 * wordSize; const int frame_size = frame::abi_112_size + spill_slots; + Label filtered; + + // Is marking active? + if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { + __ lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()), R16_thread); + } else { + guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()), R16_thread); + } + __ cmpdi(CCR0, Rtmp1, 0); + __ beq(CCR0, filtered); __ save_LR_CR(R0); __ push_frame_abi112(spill_slots, R0); @@ -628,6 +640,8 @@ class StubGenerator: public StubCodeGenerator { __ ld(count, frame_size - 3 * wordSize, R1_SP); __ pop_frame(); __ restore_LR_CR(R0); + + __ bind(filtered); } break; case BarrierSet::CardTableModRef: @@ -648,21 +662,28 @@ class StubGenerator: public StubCodeGenerator { // // The input registers and R0 are overwritten. // - void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp) { + void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp, bool branchToEnd) { BarrierSet* const bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { - __ save_LR_CR(R0); - // We need this frame only that the callee can spill LR/CR. - __ push_frame_abi112(0, R0); - - __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); - - __ pop_frame(); - __ restore_LR_CR(R0); + if (branchToEnd) { + __ save_LR_CR(R0); + // We need this frame only to spill LR. + __ push_frame_abi112(0, R0); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); + __ pop_frame(); + __ restore_LR_CR(R0); + } else { + // Tail call: fake call from stub caller by branching without linking. + address entry_point = (address)CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post); + __ mr_if_needed(R3_ARG1, addr); + __ mr_if_needed(R4_ARG2, count); + __ load_const(R11, entry_point, R0); + __ call_c_and_return_to_caller(R11); + } } break; case BarrierSet::CardTableModRef: @@ -697,9 +718,12 @@ class StubGenerator: public StubCodeGenerator { __ addi(addr, addr, 1); __ bdnz(Lstore_loop); __ bind(Lskip_loop); + + if (!branchToEnd) __ blr(); } break; case BarrierSet::ModRef: + if (!branchToEnd) __ blr(); break; default: ShouldNotReachHere(); @@ -847,30 +871,28 @@ class StubGenerator: public StubCodeGenerator { // The code is implemented(ported from sparc) as we believe it benefits JVM98, however // tracing(-XX:+TraceOptimizeFill) shows the intrinsic replacement doesn't happen at all! // - // Source code in function is_range_check_if() shows OptimizeFill relaxed the condition + // Source code in function is_range_check_if() shows that OptimizeFill relaxed the condition // for turning on loop predication optimization, and hence the behavior of "array range check" // and "loop invariant check" could be influenced, which potentially boosted JVM98. // - // We leave the code here and see if Oracle has updates in later releases(later than HS20). - // - // Generate stub for disjoint short fill. If "aligned" is true, the - // "to" address is assumed to be heapword aligned. + // Generate stub for disjoint short fill. If "aligned" is true, the + // "to" address is assumed to be heapword aligned. // // Arguments for generated stub: - // to: R3_ARG1 - // value: R4_ARG2 - // count: R5_ARG3 treated as signed + // to: R3_ARG1 + // value: R4_ARG2 + // count: R5_ARG3 treated as signed // address generate_fill(BasicType t, bool aligned, const char* name) { StubCodeMark mark(this, "StubRoutines", name); address start = __ emit_fd(); - const Register to = R3_ARG1; // source array address - const Register value = R4_ARG2; // fill value - const Register count = R5_ARG3; // elements count - const Register temp = R6_ARG4; // temp register + const Register to = R3_ARG1; // source array address + const Register value = R4_ARG2; // fill value + const Register count = R5_ARG3; // elements count + const Register temp = R6_ARG4; // temp register - //assert_clean_int(count, O3); // Make sure 'count' is clean int. + //assert_clean_int(count, O3); // Make sure 'count' is clean int. Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; Label L_fill_2_bytes, L_fill_4_bytes, L_fill_elements, L_fill_32_bytes; @@ -879,31 +901,31 @@ class StubGenerator: public StubCodeGenerator { switch (t) { case T_BYTE: shift = 2; - // clone bytes (zero extend not needed because store instructions below ignore high order bytes) + // Clone bytes (zero extend not needed because store instructions below ignore high order bytes). __ rldimi(value, value, 8, 48); // 8 bit -> 16 bit - __ cmpdi(CCR0, count, 2< 32 bit break; case T_SHORT: shift = 1; - // clone bytes (zero extend not needed because store instructions below ignore high order bytes) + // Clone bytes (zero extend not needed because store instructions below ignore high order bytes). __ rldimi(value, value, 16, 32); // 16 bit -> 32 bit - __ cmpdi(CCR0, count, 2<long as above - __ rldimi(value, value, 32, 0); // 32 bit -> 64 bit + __ li(temp, 8<long as above. + __ rldimi(value, value, 32, 0); // 32 bit -> 64 bit Label L_check_fill_8_bytes; - // Fill 32-byte chunks + // Fill 32-byte chunks. __ subf_(count, temp, count); __ blt(CCR0, L_check_fill_8_bytes); @@ -945,7 +967,7 @@ class StubGenerator: public StubCodeGenerator { __ std(value, 0, to); __ std(value, 8, to); - __ subf_(count, temp, count); // update count + __ subf_(count, temp, count); // Update count. __ std(value, 16, to); __ std(value, 24, to); @@ -968,7 +990,7 @@ class StubGenerator: public StubCodeGenerator { __ addi(to, to, 8); __ bge(CCR0, L_fill_8_bytes_loop); - // fill trailing 4 bytes + // Fill trailing 4 bytes. __ bind(L_fill_4_bytes); __ andi_(temp, count, 1< AllocatePrefetchStepSize) AllocatePrefetchStepSize = cache_line_size; - if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 3; // Optimistic value - if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 3*cache_line_size; // default is not defined ? + if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 3; // Optimistic value. + if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 3*cache_line_size; // Default is not defined? } assert(AllocatePrefetchLines > 0, "invalid value"); if (AllocatePrefetchLines < 1) // Set valid value in product VM. - AllocatePrefetchLines = 1; // Conservative value + AllocatePrefetchLines = 1; // Conservative value. if (AllocatePrefetchStyle == 3 && AllocatePrefetchDistance < cache_line_size) - AllocatePrefetchStyle = 1; // fall back if inappropriate + AllocatePrefetchStyle = 1; // Fall back if inappropriate. assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); } @@ -160,13 +161,13 @@ void VM_Version::determine_section_size() { const int code_size = (2* unroll * 32 + 100)*BytesPerInstWord; - // Allocate space for the code + // 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. + // Emit code. void (*test1)() = (void(*)())(void *)a->emit_fd(); Label l1; @@ -189,58 +190,58 @@ void VM_Version::determine_section_size() { // ;; 1 a->nop(); // 5 - a->fmr(F6, F6); // 6 - a->fmr(F7, F7); // 7 + 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 + 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->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 + 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->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 + 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->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->cmpdi(CCR0, R4, unroll); // 33 + a->bge(CCR0, l1); // 34 a->blr(); - // emit code. + // Emit code. void (*test2)() = (void(*)())(void *)a->emit_fd(); // uint32_t *code = (uint32_t *)a->pc(); @@ -382,39 +383,40 @@ void VM_Version::determine_section_size() { #endif // COMPILER2 void VM_Version::determine_features() { - const int code_size = (num_features+1+2*7)*BytesPerInstWord; // 7 InstWords for each call (function descriptor + blr instruction) + // 7 InstWords for each call (function descriptor + blr instruction). + const int code_size = (num_features+1+2*7)*BytesPerInstWord; int features = 0; // create test area - enum { BUFFER_SIZE = 2*4*K }; // needs to be >=2* max cache line size (cache line size can't exceed min page size) + enum { BUFFER_SIZE = 2*4*K }; // Needs to be >=2* max cache line size (cache line size can't exceed min page size). char test_area[BUFFER_SIZE]; char *mid_of_test_area = &test_area[BUFFER_SIZE>>1]; - // Allocate space for the code + // Allocate space for the code. ResourceMark rm; CodeBuffer cb("detect_cpu_features", code_size, 0); MacroAssembler* a = new MacroAssembler(&cb); - // emit code. + // Emit code. void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->emit_fd(); uint32_t *code = (uint32_t *)a->pc(); // Don't use R0 in ldarx. - // keep R3_ARG1 = R3 unmodified, it contains &field (see below) - // keep R4_ARG2 = R4 unmodified, it contains offset = 0 (see below) - a->fsqrt(F3, F4); // code[0] -> fsqrt_m - a->isel(R7, R5, R6, 0); // code[1] -> isel_m - a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1);// code[2] -> lxarx_m - a->cmpb(R7, R5, R6); // code[3] -> bcmp - //a->mftgpr(R7, F3); // code[4] -> mftgpr - a->popcntb(R7, R5); // code[5] -> popcntb - a->popcntw(R7, R5); // code[6] -> popcntw - a->fcfids(F3, F4); // code[7] -> fcfids - a->vand(VR0, VR0, VR0); // code[8] -> vand + // Keep R3_ARG1 unmodified, it contains &field (see below). + // Keep R4_ARG2 unmodified, it contains offset = 0 (see below). + a->fsqrt(F3, F4); // code[0] -> fsqrt_m + a->isel(R7, R5, R6, 0); // code[1] -> isel_m + a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[2] -> lxarx_m + a->cmpb(R7, R5, R6); // code[3] -> bcmp + //a->mftgpr(R7, F3); // code[4] -> mftgpr + a->popcntb(R7, R5); // code[5] -> popcntb + a->popcntw(R7, R5); // code[6] -> popcntw + a->fcfids(F3, F4); // code[7] -> fcfids + a->vand(VR0, VR0, VR0); // code[8] -> vand a->blr(); - // Emit function to set one cache line to zero - void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->emit_fd(); // emit function descriptor and get pointer to it - a->dcbz(R3_ARG1); // R3_ARG1 = R3 = addr + // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. + void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->emit_fd(); + a->dcbz(R3_ARG1); // R3_ARG1 = addr a->blr(); uint32_t *code_end = (uint32_t *)a->pc(); @@ -428,8 +430,8 @@ void VM_Version::determine_features() { } // Measure cache line size. - memset(test_area, 0xFF, BUFFER_SIZE); // fill test area with 0xFF - (*zero_cacheline_func_ptr)(mid_of_test_area); // call function which executes dcbz to the middle + memset(test_area, 0xFF, BUFFER_SIZE); // Fill test area with 0xFF. + (*zero_cacheline_func_ptr)(mid_of_test_area); // Call function which executes dcbz to the middle. int count = 0; // count zeroed bytes for (int i = 0; i < BUFFER_SIZE; i++) if (test_area[i] == 0) count++; guarantee(is_power_of_2(count), "cache line size needs to be a power of 2"); diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp index 6a608e93262..c9e5f5eccac 100644 --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -113,7 +113,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // If the vtable entry is null, the method is abstract. address ame_addr = __ pc(); // ame = abstract method error - __ ld_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); + __ load_with_trap_null_check(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); __ mtctr(R12_scratch2); __ bctr(); masm->flush(); @@ -147,7 +147,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { // Entry arguments: // R19_method: Interface - // R3_ARG1: Receiver + // R3_ARG1: Receiver // const Register rcvr_klass = R11_scratch1; diff --git a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp index 2eb4922aea5..93e5ed159cd 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/orderAccess_aix_ppc.inline.hpp @@ -34,114 +34,114 @@ // // Machine barrier instructions: // -// - ppc_sync Two-way memory barrier, aka fence. -// - ppc_lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load -// - ppc_eieio orders Store|Store -// - ppc_isync Invalidates speculatively executed instructions, -// but isync may complete before storage accesses -// associated with instructions preceding isync have -// been performed. +// - sync Two-way memory barrier, aka fence. +// - lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - eieio orders Store|Store +// - isync Invalidates speculatively executed instructions, +// but isync may complete before storage accesses +// associated with instructions preceding isync have +// been performed. // // Semantic barrier instructions: // (as defined in orderAccess.hpp) // -// - ppc_release orders Store|Store, (maps to ppc_lwsync) -// Load|Store -// - ppc_acquire orders Load|Store, (maps to ppc_lwsync) -// Load|Load -// - ppc_fence orders Store|Store, (maps to ppc_sync) -// Load|Store, -// Load|Load, -// Store|Load +// - release orders Store|Store, (maps to lwsync) +// Load|Store +// - acquire orders Load|Store, (maps to lwsync) +// Load|Load +// - fence orders Store|Store, (maps to sync) +// Load|Store, +// Load|Load, +// Store|Load // -#define inlasm_ppc_sync() __asm__ __volatile__ ("sync" : : : "memory"); -#define inlasm_ppc_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); -#define inlasm_ppc_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); -#define inlasm_ppc_isync() __asm__ __volatile__ ("isync" : : : "memory"); -#define inlasm_ppc_release() inlasm_ppc_lwsync(); -#define inlasm_ppc_acquire() inlasm_ppc_lwsync(); +#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); +#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory"); +#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory"); +#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory"); +#define inlasm_release() inlasm_lwsync(); +#define inlasm_acquire() inlasm_lwsync(); // Use twi-isync for load_acquire (faster than lwsync). // ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"): -// #define inlasm_ppc_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); -#define inlasm_ppc_acquire_reg(X) inlasm_ppc_lwsync(); -#define inlasm_ppc_fence() inlasm_ppc_sync(); +// #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory"); +#define inlasm_acquire_reg(X) inlasm_lwsync(); +#define inlasm_fence() inlasm_sync(); -inline void OrderAccess::loadload() { inlasm_ppc_lwsync(); } -inline void OrderAccess::storestore() { inlasm_ppc_lwsync(); } -inline void OrderAccess::loadstore() { inlasm_ppc_lwsync(); } -inline void OrderAccess::storeload() { inlasm_ppc_fence(); } +inline void OrderAccess::loadload() { inlasm_lwsync(); } +inline void OrderAccess::storestore() { inlasm_lwsync(); } +inline void OrderAccess::loadstore() { inlasm_lwsync(); } +inline void OrderAccess::storeload() { inlasm_fence(); } -inline void OrderAccess::acquire() { inlasm_ppc_acquire(); } -inline void OrderAccess::release() { inlasm_ppc_release(); } -inline void OrderAccess::fence() { inlasm_ppc_fence(); } +inline void OrderAccess::acquire() { inlasm_acquire(); } +inline void OrderAccess::release() { inlasm_release(); } +inline void OrderAccess::fence() { inlasm_fence(); } -inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_ppc_acquire_reg(t); return t; } -inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_ppc_acquire_reg(t); return t; } +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { register jbyte t = *p; inlasm_acquire_reg(t); return t; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { register jshort t = *p; inlasm_acquire_reg(t); return t; } +inline jint OrderAccess::load_acquire(volatile jint* p) { register jint t = *p; inlasm_acquire_reg(t); return t; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { register jlong t = *p; inlasm_acquire_reg(t); return t; } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { register jubyte t = *p; inlasm_acquire_reg(t); return t; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { register jushort t = *p; inlasm_acquire_reg(t); return t; } +inline juint OrderAccess::load_acquire(volatile juint* p) { register juint t = *p; inlasm_acquire_reg(t); return t; } inline julong OrderAccess::load_acquire(volatile julong* p) { return (julong)load_acquire((volatile jlong*)p); } -inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_ppc_acquire(); return t; } -inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_ppc_acquire(); return t; } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { register jfloat t = *p; inlasm_acquire(); return t; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { register jdouble t = *p; inlasm_acquire(); return t; } inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return (intptr_t)load_acquire((volatile jlong*)p); } inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return (void*) load_acquire((volatile jlong*)p); } -inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; } +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; } -inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; } +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; } -inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; inlasm_fence(); } -inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; inlasm_fence(); } +inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { inlasm_release(); *p = v; inlasm_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_ppc_release(); *p = v; inlasm_ppc_fence(); } -inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_ppc_release(); *(void* volatile *)p = v; inlasm_ppc_fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { inlasm_release(); *p = v; inlasm_fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { inlasm_release(); *(void* volatile *)p = v; inlasm_fence(); } -#undef inlasm_ppc_sync -#undef inlasm_ppc_lwsync -#undef inlasm_ppc_eieio -#undef inlasm_ppc_isync -#undef inlasm_ppc_release -#undef inlasm_ppc_acquire -#undef inlasm_ppc_fence +#undef inlasm_sync +#undef inlasm_lwsync +#undef inlasm_eieio +#undef inlasm_isync +#undef inlasm_release +#undef inlasm_acquire +#undef inlasm_fence #endif // OS_CPU_AIX_OJDKPPC_VM_ORDERACCESS_AIX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index fe3769f3068..f2bbfb34b9e 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -67,7 +67,7 @@ address os::current_stack_pointer() { address csp; #if !defined(USE_XLC_BUILTINS) - // inline assembly for `ppc_mr regno(csp), PPC_SP': + // inline assembly for `mr regno(csp), R1_SP': __asm__ __volatile__ ("mr %0, 1":"=r"(csp):); #else csp = (address) __builtin_frame_address(0); @@ -263,7 +263,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec tty->print_raw_cr("An irrecoverable stack overflow has occurred."); goto report_and_die; } else { - // this means a segv happened inside our stack, but not in + // This means a segv happened inside our stack, but not in // the guarded zone. I'd like to know when this happens, tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone."); goto report_and_die; @@ -312,53 +312,57 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec // in the zero page, because it is filled with 0x0. We ignore // explicit SIGILLs in the zero page. if (sig == SIGILL && (pc < (address) 0x200)) { - if (TraceTraps) + if (TraceTraps) { tty->print_raw_cr("SIGILL happened inside zero page."); + } goto report_and_die; } // Handle signal from NativeJump::patch_verified_entry(). if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) || (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + } stub = SharedRuntime::get_handle_wrong_method_stub(); goto run_stub; } else if (sig == SIGSEGV && os::is_poll_address(addr)) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc); + } stub = SharedRuntime::get_poll_stub(pc); goto run_stub; } - // SIGTRAP-based ic miss check in compiled code + // SIGTRAP-based ic miss check in compiled code. else if (sig == SIGTRAP && TrapBasedICMissChecks && nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::get_ic_miss_stub(); goto run_stub; } -#ifdef COMPILER2 // SIGTRAP-based implicit null check in compiled code. else if (sig == SIGTRAP && TrapBasedNullChecks && nativeInstruction_at(pc)->is_sigtrap_null_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); goto run_stub; } -#endif // SIGSEGV-based implicit null check in compiled code. else if (sig == SIGSEGV && ImplicitNullChecks && CodeCache::contains((void*) pc) && !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); } @@ -366,8 +370,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec // SIGTRAP-based implicit range check in compiled code. else if (sig == SIGTRAP && TrapBasedRangeChecks && nativeInstruction_at(pc)->is_sigtrap_range_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); goto run_stub; } diff --git a/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp index 6e522364b17..d9a8048963d 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp @@ -58,35 +58,35 @@ inline jlong Atomic::load(volatile jlong* src) { return *src; } - sync two-way memory barrier, aka fence - lwsync orders Store|Store, - Load|Store, - Load|Load, - but not Store|Load + Load|Store, + Load|Load, + but not Store|Load - eieio orders memory accesses for device memory (only) - isync invalidates speculatively executed instructions - From the POWER ISA 2.06 documentation: - "[...] an isync instruction prevents the execution of - instructions following the isync until instructions - preceding the isync have completed, [...]" - From IBM's AIX assembler reference: - "The isync [...] instructions causes the processor to - refetch any instructions that might have been fetched - prior to the isync instruction. The instruction isync - causes the processor to wait for all previous instructions - to complete. Then any instructions already fetched are - discarded and instruction processing continues in the - environment established by the previous instructions." + From the POWER ISA 2.06 documentation: + "[...] an isync instruction prevents the execution of + instructions following the isync until instructions + preceding the isync have completed, [...]" + From IBM's AIX assembler reference: + "The isync [...] instructions causes the processor to + refetch any instructions that might have been fetched + prior to the isync instruction. The instruction isync + causes the processor to wait for all previous instructions + to complete. Then any instructions already fetched are + discarded and instruction processing continues in the + environment established by the previous instructions." semantic barrier instructions: (as defined in orderAccess.hpp) - release orders Store|Store, (maps to lwsync) - Load|Store + Load|Store - acquire orders Load|Store, (maps to lwsync) - Load|Load + Load|Load - fence orders Store|Store, (maps to sync) - Load|Store, - Load|Load, - Store|Load + Load|Store, + Load|Load, + Store|Load */ #define strasm_sync "\n sync \n" diff --git a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp index c237322232d..dcc2375f878 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/orderAccess_linux_ppc.inline.hpp @@ -40,26 +40,26 @@ // // - sync Two-way memory barrier, aka fence. // - lwsync orders Store|Store, -// Load|Store, -// Load|Load, -// but not Store|Load +// Load|Store, +// Load|Load, +// but not Store|Load // - eieio orders Store|Store // - isync Invalidates speculatively executed instructions, -// but isync may complete before storage accesses -// associated with instructions preceding isync have -// been performed. +// but isync may complete before storage accesses +// associated with instructions preceding isync have +// been performed. // // Semantic barrier instructions: // (as defined in orderAccess.hpp) // // - release orders Store|Store, (maps to lwsync) -// Load|Store +// Load|Store // - acquire orders Load|Store, (maps to lwsync) -// Load|Load +// Load|Load // - fence orders Store|Store, (maps to sync) -// Load|Store, -// Load|Load, -// Store|Load +// Load|Store, +// Load|Load, +// Store|Load // #define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory"); diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index 10b26495c59..ccfd54ba9de 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -284,16 +284,18 @@ JVM_handle_linux_signal(int sig, // in the zero page, because it is filled with 0x0. We ignore // explicit SIGILLs in the zero page. if (sig == SIGILL && (pc < (address) 0x200)) { - if (TraceTraps) + if (TraceTraps) { tty->print_raw_cr("SIGILL happened inside zero page."); + } goto report_and_die; } // Handle signal from NativeJump::patch_verified_entry(). if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) || (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + } stub = SharedRuntime::get_handle_wrong_method_stub(); } @@ -304,24 +306,27 @@ JVM_handle_linux_signal(int sig, // (address)info->si_addr == os::get_standard_polling_page() // doesn't work for us. We use: ((NativeInstruction*)pc)->is_safepoint_poll()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc); + } stub = SharedRuntime::get_poll_stub(pc); } // SIGTRAP-based ic miss check in compiled code. else if (sig == SIGTRAP && TrapBasedICMissChecks && nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::get_ic_miss_stub(); } // SIGTRAP-based implicit null check in compiled code. else if (sig == SIGTRAP && TrapBasedNullChecks && nativeInstruction_at(pc)->is_sigtrap_null_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); } @@ -329,8 +334,9 @@ JVM_handle_linux_signal(int sig, else if (sig == SIGSEGV && ImplicitNullChecks && CodeCache::contains((void*) pc) && !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); } @@ -338,8 +344,9 @@ JVM_handle_linux_signal(int sig, // SIGTRAP-based implicit range check in compiled code. else if (sig == SIGTRAP && TrapBasedRangeChecks && nativeInstruction_at(pc)->is_sigtrap_range_check()) { - if (TraceTraps) + if (TraceTraps) { tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc); + } stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); } #endif From 2131424a64a2092877b7fb64ea0a2cef7bd9c094 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 11 Dec 2013 12:28:09 +0100 Subject: [PATCH 059/265] 8029957: PPC64 (part 213): cppInterpreter: memory ordering for object initialization Add StoreStore barriers after object initialization and after constructor calls in the C++ interpreter. Reviewed-by: kvn --- .../vm/interpreter/bytecodeInterpreter.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 6b9dd574b30..73b4886a358 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2240,6 +2240,9 @@ run: } result->set_klass_gap(0); result->set_klass(k_entry); + // Must prevent reordering of stores for object initialization + // with stores that publish the new object. + OrderAccess::storestore(); SET_STACK_OBJECT(result, 0); UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1); } @@ -2248,6 +2251,9 @@ run: // Slow case allocation CALL_VM(InterpreterRuntime::_new(THREAD, METHOD->constants(), index), handle_exception); + // Must prevent reordering of stores for object initialization + // with stores that publish the new object. + OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), 0); THREAD->set_vm_result(NULL); UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1); @@ -2257,6 +2263,9 @@ run: jint size = STACK_INT(-1); CALL_VM(InterpreterRuntime::anewarray(THREAD, METHOD->constants(), index, size), handle_exception); + // Must prevent reordering of stores for object initialization + // with stores that publish the new object. + OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -1); THREAD->set_vm_result(NULL); UPDATE_PC_AND_CONTINUE(3); @@ -2271,6 +2280,9 @@ run: //adjust pointer to start of stack element CALL_VM(InterpreterRuntime::multianewarray(THREAD, dimarray), handle_exception); + // Must prevent reordering of stores for object initialization + // with stores that publish the new object. + OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -dims); THREAD->set_vm_result(NULL); UPDATE_PC_AND_TOS_AND_CONTINUE(4, -(dims-1)); @@ -2693,6 +2705,9 @@ run: jint size = STACK_INT(-1); CALL_VM(InterpreterRuntime::newarray(THREAD, atype, size), handle_exception); + // Must prevent reordering of stores for object initialization + // with stores that publish the new object. + OrderAccess::storestore(); SET_STACK_OBJECT(THREAD->vm_result(), -1); THREAD->set_vm_result(NULL); @@ -2926,6 +2941,12 @@ run: } // handle_Early_Return handle_return: { + // A storestore barrier is required to order initialization of + // final fields with publishing the reference to the object that + // holds the field. Without the barrier the value of final fields + // can be observed to change. + OrderAccess::storestore(); + DECACHE_STATE(); bool suppress_error = istate->msg() == popping_frame || istate->msg() == early_return; From 45bbfbc7ca2c5fcfa08a996c5607516662283e2d Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 13 Feb 2014 16:38:49 +0100 Subject: [PATCH 060/265] 8034769: Move logutil in corba to make/tools Reviewed-by: alanb, ihse, tbell --- corba/make/CompileCorba.gmk | 3 +- corba/make/GensrcCorba.gmk | 137 +++++++++++++++--- .../tools}/logutil/IndentingPrintWriter.java | 2 +- .../classes/build/tools}/logutil/Input.java | 2 +- .../build/tools}/logutil/InputCode.java | 2 +- .../build/tools}/logutil/InputException.java | 2 +- .../src/classes/build/tools}/logutil/MC.java | 2 +- .../build/tools}/logutil/StringUtil.java | 2 +- .../stripproperties/StripPropertiesCorba.java | 0 .../com/sun/tools/corba/se/logutil/Makefile | 93 ------------ 10 files changed, 127 insertions(+), 118 deletions(-) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/IndentingPrintWriter.java (99%) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/Input.java (99%) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/InputCode.java (98%) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/InputException.java (98%) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/MC.java (99%) rename corba/{src/share/classes/com/sun/tools/corba/se => make/src/classes/build/tools}/logutil/StringUtil.java (98%) rename corba/make/{tools/src => src/classes}/build/tools/stripproperties/StripPropertiesCorba.java (100%) delete mode 100644 corba/src/share/classes/com/sun/tools/corba/se/logutil/Makefile diff --git a/corba/make/CompileCorba.gmk b/corba/make/CompileCorba.gmk index 16e0c4e679d..f50d4ca4687 100644 --- a/corba/make/CompileCorba.gmk +++ b/corba/make/CompileCorba.gmk @@ -37,8 +37,7 @@ include CommonCorba.gmk $(eval $(call SetupJavaCompilation,BUILD_CORBA, \ SETUP := GENERATE_NEWBYTECODE, \ SRC := $(CORBA_TOPDIR)/src/share/classes $(CORBA_OUTPUTDIR)/gensrc, \ - EXCLUDES := com/sun/corba/se/PortableActivationIDL \ - com/sun/tools/corba/se/logutil, \ + EXCLUDES := com/sun/corba/se/PortableActivationIDL, \ EXCLUDE_FILES := com/sun/corba/se/impl/presentation/rmi/JNDIStateFactoryImpl.java \ com/sun/corba/se/spi/presentation/rmi/StubWrapper.java \ com/sun/org/omg/CORBA/IDLTypeOperations.java \ diff --git a/corba/make/GensrcCorba.gmk b/corba/make/GensrcCorba.gmk index 61030ed5af7..8dbf5102eda 100644 --- a/corba/make/GensrcCorba.gmk +++ b/corba/make/GensrcCorba.gmk @@ -34,14 +34,17 @@ include CommonCorba.gmk ################################################################################ -$(eval $(call SetupJavaCompilation,BUILD_STRIPPROP, \ +$(eval $(call SetupJavaCompilation,BUILD_TOOLS, \ SETUP := GENERATE_OLDBYTECODE, \ - SRC := $(CORBA_TOPDIR)/make/tools/src, \ - BIN := $(CORBA_OUTPUTDIR)/stripprop_classes)) + SRC := $(CORBA_TOPDIR)/make/src/classes, \ + BIN := $(CORBA_OUTPUTDIR)/tools_classes)) -TOOL_STRIPPROP_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/stripprop_classes \ +TOOL_STRIPPROP_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/tools_classes \ build.tools.stripproperties.StripPropertiesCorba +TOOL_LOGUTIL_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/tools_classes \ + build.tools.logutil.MC + $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := $(CORBA_TOPDIR)/src/share/classes, \ @@ -53,21 +56,12 @@ $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \ TOOL_IDLJ_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/idlj_classes \ com.sun.tools.corba.se.idl.toJavaPortable.Compile -$(eval $(call SetupJavaCompilation,BUILD_LOGUTIL, \ - SETUP := GENERATE_OLDBYTECODE, \ - SRC := $(CORBA_TOPDIR)/src/share/classes, \ - BIN := $(CORBA_OUTPUTDIR)/logutil_classes, \ - INCLUDES := com/sun/tools/corba/se/logutil)) - -TOOL_LOGUTIL_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/logutil_classes \ - com.sun.tools.corba.se.logutil.MC - ################################################################################ # Generate LogWrapper classes $(CORBA_OUTPUTDIR)/gensrc/com/sun/corba/se/impl/logging/%SystemException.java: \ $(CORBA_TOPDIR)/src/share/classes/com/sun/corba/se/spi/logging/data/%.mc \ - $(BUILD_LOGUTIL) + $(BUILD_TOOLS) $(MKDIR) -p $(@D) $(RM) -f $(@D)/_the_wrappers.d $(ECHO) $(LOG_INFO) Generating class file from $*.mc @@ -90,7 +84,7 @@ $(CORBA_OUTPUTDIR)/gensrc/com/sun/corba/se/impl/logging/LogStrings.properties: \ # The resources files are generated from lisp-like .mc files. $(CORBA_OUTPUTDIR)/logwrappers/%SystemException.resource: \ $(CORBA_TOPDIR)/src/share/classes/com/sun/corba/se/spi/logging/data/%.mc \ - $(BUILD_LOGUTIL) + $(BUILD_TOOLS) $(MKDIR) -p $(@D) $(RM) -f $(@D)/_the_wrappers.d $(ECHO) $(LOG_INFO) Generating resource file from $*.mc @@ -111,6 +105,115 @@ LOGWRAPPER_TARGETS := \ ################################################################################ # Build the IDLs. +IDL_DELETES := \ + org/omg/DynamicAny/*POA* \ + org/omg/DynamicAny/*Holder* \ + org/omg/DynamicAny/DynValueBoxHelper.java \ + org/omg/DynamicAny/DynValueCommonHelper.java \ + org/omg/DynamicAny/_DynValueCommonStub.java \ + org/omg/DynamicAny/_DynValueBoxStub.java \ + org/omg/DynamicAny/DynAnyPackage/TypeMismatchHolder.java \ + org/omg/DynamicAny/DynAnyPackage/InvalidValueHolder.java \ + org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHolder.java \ + org/omg/IOP/BI_DIR_IIOP.java \ + org/omg/IOP/ChainBypassCheck.java \ + org/omg/IOP/ChainBypassInfo.java \ + org/omg/IOP/FORWARDED_IDENTITY.java \ + org/omg/IOP/INVOCATION_POLICIES.java \ + org/omg/IOP/LogicalThreadId.java \ + org/omg/IOP/SendingContextRunTime.java \ + org/omg/IOP/UnknownExceptionInfo.java \ + org/omg/IOP/TaggedComponentSeqHolder.java \ + org/omg/PortableServer/CurrentPackage/NoContextHolder.java \ + org/omg/PortableServer/ForwardRequestHolder.java \ + org/omg/PortableServer/IdAssignmentPolicyValueHelper.java \ + org/omg/PortableServer/IdAssignmentPolicyValueHolder.java \ + org/omg/PortableServer/IdUniquenessPolicyValueHelper.java \ + org/omg/PortableServer/IdUniquenessPolicyValueHolder.java \ + org/omg/PortableServer/ImplicitActivationPolicyValueHelper.java \ + org/omg/PortableServer/ImplicitActivationPolicyValueHolder.java \ + org/omg/PortableServer/LifespanPolicyValueHelper.java \ + org/omg/PortableServer/LifespanPolicyValueHolder.java \ + org/omg/PortableServer/ServantRetentionPolicyValueHelper.java \ + org/omg/PortableServer/ServantRetentionPolicyValueHolder.java \ + org/omg/PortableServer/ObjectIdHelper.java \ + org/omg/PortableServer/ObjectIdHolder.java \ + org/omg/PortableServer/POAListHelper.java \ + org/omg/PortableServer/POAListHolder.java \ + org/omg/PortableServer/POAManagerPackage/AdapterInactiveHolder.java \ + org/omg/PortableServer/POAManagerPackage/StateHelper.java \ + org/omg/PortableServer/POAManagerPackage/StateHolder.java \ + org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHolder.java \ + org/omg/PortableServer/POAPackage/AdapterNonExistentHolder.java \ + org/omg/PortableServer/POAPackage/InvalidPolicyHolder.java \ + org/omg/PortableServer/POAPackage/NoServantHolder.java \ + org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHolder.java \ + org/omg/PortableServer/POAPackage/ObjectNotActiveHolder.java \ + org/omg/PortableServer/POAPackage/ServantAlreadyActiveHolder.java \ + org/omg/PortableServer/POAPackage/ServantNotActiveHolder.java \ + org/omg/PortableServer/POAPackage/WrongAdapterHolder.java \ + org/omg/PortableServer/POAPackage/WrongPolicyHolder.java \ + org/omg/PortableServer/RequestProcessingPolicyValueHelper.java \ + org/omg/PortableServer/RequestProcessingPolicyValueHolder.java \ + org/omg/PortableServer/ServantActivatorHolder.java \ + org/omg/PortableServer/ServantLocatorHolder.java \ + org/omg/PortableServer/ThreadPolicyValueHelper.java \ + org/omg/PortableServer/ThreadPolicyValueHolder.java \ + org/omg/PortableInterceptor/ClientRequestInfoHelper.java \ + org/omg/PortableInterceptor/ClientRequestInterceptorHelper.java \ + org/omg/PortableInterceptor/IORInfoHelper.java \ + org/omg/PortableInterceptor/IORInterceptorHelper.java \ + org/omg/PortableInterceptor/InterceptorHelper.java \ + org/omg/PortableInterceptor/ORBInitInfoHelper.java \ + org/omg/PortableInterceptor/ORBInitializerHelper.java \ + org/omg/PortableInterceptor/PolicyFactoryHelper.java \ + org/omg/PortableInterceptor/ReplyStatusHelper.java \ + org/omg/PortableInterceptor/RequestInfoHelper.java \ + org/omg/PortableInterceptor/ServerRequestInfoHelper.java \ + org/omg/PortableInterceptor/ServerRequestInterceptorHelper.java \ + org/omg/PortableInterceptor/SlotIdHelper.java \ + org/omg/PortableInterceptor/ClientRequestInfoHolder.java \ + org/omg/PortableInterceptor/ClientRequestInterceptorHolder.java \ + org/omg/PortableInterceptor/CurrentHolder.java \ + org/omg/PortableInterceptor/ForwardRequestHolder.java \ + org/omg/PortableInterceptor/IORInfoHolder.java \ + org/omg/PortableInterceptor/IORInterceptorHolder.java \ + org/omg/PortableInterceptor/InterceptorHolder.java \ + org/omg/PortableInterceptor/InvalidSlotHolder.java \ + org/omg/PortableInterceptor/ORBInitInfoHolder.java \ + org/omg/PortableInterceptor/ORBInitializerHolder.java \ + org/omg/PortableInterceptor/PolicyFactoryHolder.java \ + org/omg/PortableInterceptor/RequestInfoHolder.java \ + org/omg/PortableInterceptor/ServerRequestInfoHolder.java \ + org/omg/PortableInterceptor/ServerRequestInterceptorHolder.java \ + org/omg/PortableInterceptor/TaggedComponentSeqHolder.java \ + org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHolder.java \ + org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHolder.java \ + org/omg/IOP/CodecPackage/FormatMismatchHolder.java \ + org/omg/IOP/CodecPackage/InvalidTypeForEncodingHolder.java \ + org/omg/IOP/CodecPackage/TypeMismatchHolder.java \ + org/omg/IOP/CodecHelper.java \ + org/omg/IOP/EncodingFormatHelper.java \ + org/omg/IOP/EncodingHelper.java \ + org/omg/IOP/CodecFactoryPackage/UnknownEncodingHolder.java \ + org/omg/IOP/CodecFactoryHolder.java \ + org/omg/IOP/CodecHolder.java \ + org/omg/IOP/EncodingHolder.java \ + org/omg/IOP/TaggedComponentSeqHelper.java \ + org/omg/Dynamic/ContextListHelper.java \ + org/omg/Dynamic/ExceptionListHelper.java \ + org/omg/Dynamic/ParameterHolder.java \ + org/omg/Dynamic/ParameterListHolder.java \ + org/omg/Dynamic/ExceptionListHolder.java \ + org/omg/Dynamic/ParameterHelper.java \ + org/omg/Dynamic/ParameterListHelper.java \ + org/omg/Dynamic/RequestContextHelper.java \ + org/omg/CORBA/OctetSeqHelper.java \ + org/omg/CORBA/OctetSeqHolder.java \ + org/omg/CORBA/PolicyError.java \ + org/omg/CORBA/RepositoryIdHelper.java \ + # + $(eval $(call SetupIdlCompilation,BUILD_IDLS, \ IDLJ := $(TOOL_IDLJ_CMD), \ SRC := $(CORBA_TOPDIR)/src/share/classes, \ @@ -122,7 +225,7 @@ $(eval $(call SetupIdlCompilation,BUILD_IDLS, \ INCLUDES := %, \ OLDIMPLBASES := com/sun/corba/se/PortableActivationIDL/activation.idl \ com/sun/corba/se/spi/activation/activation.idl, \ - DELETES := DYNANYDELETEFILES org/omg/DynamicAny/*POA* org/omg/DynamicAny/*Holder* org/omg/DynamicAny/DynValueBoxHelper.java org/omg/DynamicAny/DynValueCommonHelper.java org/omg/DynamicAny/_DynValueCommonStub.java org/omg/DynamicAny/_DynValueBoxStub.java org/omg/DynamicAny/DynAnyPackage/TypeMismatchHolder.java org/omg/DynamicAny/DynAnyPackage/InvalidValueHolder.java org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHolder.java IOPDELETEFILES org/omg/IOP/BI_DIR_IIOP.java org/omg/IOP/ChainBypassCheck.java org/omg/IOP/ChainBypassInfo.java org/omg/IOP/FORWARDED_IDENTITY.java org/omg/IOP/INVOCATION_POLICIES.java org/omg/IOP/LogicalThreadId.java org/omg/IOP/SendingContextRunTime.java org/omg/IOP/UnknownExceptionInfo.java org/omg/IOP/TaggedComponentSeqHolder.java POAHELHOLFILES org/omg/PortableServer/CurrentPackage/NoContextHolder.java org/omg/PortableServer/ForwardRequestHolder.java org/omg/PortableServer/IdAssignmentPolicyValueHelper.java org/omg/PortableServer/IdAssignmentPolicyValueHolder.java org/omg/PortableServer/IdUniquenessPolicyValueHelper.java org/omg/PortableServer/IdUniquenessPolicyValueHolder.java org/omg/PortableServer/ImplicitActivationPolicyValueHelper.java org/omg/PortableServer/ImplicitActivationPolicyValueHolder.java org/omg/PortableServer/LifespanPolicyValueHelper.java org/omg/PortableServer/LifespanPolicyValueHolder.java org/omg/PortableServer/ServantRetentionPolicyValueHelper.java org/omg/PortableServer/ServantRetentionPolicyValueHolder.java org/omg/PortableServer/ObjectIdHelper.java org/omg/PortableServer/ObjectIdHolder.java org/omg/PortableServer/POAListHelper.java org/omg/PortableServer/POAListHolder.java org/omg/PortableServer/POAManagerPackage/AdapterInactiveHolder.java org/omg/PortableServer/POAManagerPackage/StateHelper.java org/omg/PortableServer/POAManagerPackage/StateHolder.java org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHolder.java org/omg/PortableServer/POAPackage/AdapterNonExistentHolder.java org/omg/PortableServer/POAPackage/InvalidPolicyHolder.java org/omg/PortableServer/POAPackage/NoServantHolder.java org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHolder.java org/omg/PortableServer/POAPackage/ObjectNotActiveHolder.java org/omg/PortableServer/POAPackage/ServantAlreadyActiveHolder.java org/omg/PortableServer/POAPackage/ServantNotActiveHolder.java org/omg/PortableServer/POAPackage/WrongAdapterHolder.java org/omg/PortableServer/POAPackage/WrongPolicyHolder.java org/omg/PortableServer/RequestProcessingPolicyValueHelper.java org/omg/PortableServer/RequestProcessingPolicyValueHolder.java org/omg/PortableServer/ServantActivatorHolder.java org/omg/PortableServer/ServantLocatorHolder.java org/omg/PortableServer/ThreadPolicyValueHelper.java org/omg/PortableServer/ThreadPolicyValueHolder.java PIHELHOLFILES org/omg/PortableInterceptor/ClientRequestInfoHelper.java org/omg/PortableInterceptor/ClientRequestInterceptorHelper.java org/omg/PortableInterceptor/IORInfoHelper.java org/omg/PortableInterceptor/IORInterceptorHelper.java org/omg/PortableInterceptor/InterceptorHelper.java org/omg/PortableInterceptor/ORBInitInfoHelper.java org/omg/PortableInterceptor/ORBInitializerHelper.java org/omg/PortableInterceptor/PolicyFactoryHelper.java org/omg/PortableInterceptor/ReplyStatusHelper.java org/omg/PortableInterceptor/RequestInfoHelper.java org/omg/PortableInterceptor/ServerRequestInfoHelper.java org/omg/PortableInterceptor/ServerRequestInterceptorHelper.java org/omg/PortableInterceptor/SlotIdHelper.java org/omg/PortableInterceptor/ClientRequestInfoHolder.java org/omg/PortableInterceptor/ClientRequestInterceptorHolder.java org/omg/PortableInterceptor/CurrentHolder.java org/omg/PortableInterceptor/ForwardRequestHolder.java org/omg/PortableInterceptor/IORInfoHolder.java org/omg/PortableInterceptor/IORInterceptorHolder.java org/omg/PortableInterceptor/InterceptorHolder.java org/omg/PortableInterceptor/InvalidSlotHolder.java org/omg/PortableInterceptor/ORBInitInfoHolder.java org/omg/PortableInterceptor/ORBInitializerHolder.java org/omg/PortableInterceptor/PolicyFactoryHolder.java org/omg/PortableInterceptor/RequestInfoHolder.java org/omg/PortableInterceptor/ServerRequestInfoHolder.java org/omg/PortableInterceptor/ServerRequestInterceptorHolder.java org/omg/PortableInterceptor/TaggedComponentSeqHolder.java org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHolder.java org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHolder.java org/omg/IOP/CodecPackage/FormatMismatchHolder.java org/omg/IOP/CodecPackage/InvalidTypeForEncodingHolder.java org/omg/IOP/CodecPackage/TypeMismatchHolder.java org/omg/IOP/CodecHelper.java org/omg/IOP/EncodingFormatHelper.java org/omg/IOP/EncodingHelper.java org/omg/IOP/CodecFactoryPackage/UnknownEncodingHolder.java org/omg/IOP/CodecFactoryHolder.java org/omg/IOP/CodecHolder.java org/omg/IOP/EncodingHolder.java org/omg/IOP/TaggedComponentSeqHelper.java org/omg/Dynamic/ContextListHelper.java org/omg/Dynamic/ExceptionListHelper.java org/omg/Dynamic/ParameterHolder.java org/omg/Dynamic/ParameterListHolder.java org/omg/Dynamic/ExceptionListHolder.java org/omg/Dynamic/ParameterHelper.java org/omg/Dynamic/ParameterListHelper.java org/omg/Dynamic/RequestContextHelper.java CORBAX org/omg/CORBA/OctetSeqHelper.java org/omg/CORBA/OctetSeqHolder.java org/omg/CORBA/PolicyError.java org/omg/CORBA/RepositoryIdHelper.java)) + DELETES := $(IDL_DELETES))) $(BUILD_IDLS): $(BUILD_IDLJ) @@ -142,7 +245,7 @@ STRIP_PROP_CMDLINE := $(subst _SPACE_, $(SPACE), \ $(addprefix _SPACE_, $(STRIP_PROP_FILES)))) $(CORBA_OUTPUTDIR)/_the.stripped_properties: $(STRIP_PROP_SRC_FILES) \ - $(BUILD_STRIPPROP) + $(BUILD_TOOLS) $(MKDIR) -p $(sort $(dir $(STRIP_PROP_FILES))) $(call ListPathsSafely,STRIP_PROP_CMDLINE,\n, >> $(CORBA_OUTPUTDIR)/_the.strip_prop.cmdline) $(TOOL_STRIPPROP_CMD) @$(CORBA_OUTPUTDIR)/_the.strip_prop.cmdline diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java b/corba/make/src/classes/build/tools/logutil/IndentingPrintWriter.java similarity index 99% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java rename to corba/make/src/classes/build/tools/logutil/IndentingPrintWriter.java index 164b8cb226d..d6272db118b 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java +++ b/corba/make/src/classes/build/tools/logutil/IndentingPrintWriter.java @@ -23,7 +23,7 @@ * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; import java.io.PrintWriter ; import java.io.Writer ; diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java b/corba/make/src/classes/build/tools/logutil/Input.java similarity index 99% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java rename to corba/make/src/classes/build/tools/logutil/Input.java index c0e5cf65e1b..62c80a980af 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java +++ b/corba/make/src/classes/build/tools/logutil/Input.java @@ -23,7 +23,7 @@ * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; import java.io.BufferedReader; import java.io.File; diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java b/corba/make/src/classes/build/tools/logutil/InputCode.java similarity index 98% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java rename to corba/make/src/classes/build/tools/logutil/InputCode.java index 1e26e726306..b033382196b 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java +++ b/corba/make/src/classes/build/tools/logutil/InputCode.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; public class InputCode { diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java b/corba/make/src/classes/build/tools/logutil/InputException.java similarity index 98% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java rename to corba/make/src/classes/build/tools/logutil/InputException.java index d4aecc05c3a..5b13de20496 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java +++ b/corba/make/src/classes/build/tools/logutil/InputException.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; import java.util.LinkedList; import java.util.Queue; diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java b/corba/make/src/classes/build/tools/logutil/MC.java similarity index 99% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java rename to corba/make/src/classes/build/tools/logutil/MC.java index b2fd98a5205..c02602ec0b7 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java +++ b/corba/make/src/classes/build/tools/logutil/MC.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; import java.io.File; import java.io.FileNotFoundException; diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/StringUtil.java b/corba/make/src/classes/build/tools/logutil/StringUtil.java similarity index 98% rename from corba/src/share/classes/com/sun/tools/corba/se/logutil/StringUtil.java rename to corba/make/src/classes/build/tools/logutil/StringUtil.java index 2eacfe9aeaa..c56023545df 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/StringUtil.java +++ b/corba/make/src/classes/build/tools/logutil/StringUtil.java @@ -23,7 +23,7 @@ * questions. */ -package com.sun.tools.corba.se.logutil; +package build.tools.logutil; public abstract class StringUtil { /** Take a string containing underscores, and return a string diff --git a/corba/make/tools/src/build/tools/stripproperties/StripPropertiesCorba.java b/corba/make/src/classes/build/tools/stripproperties/StripPropertiesCorba.java similarity index 100% rename from corba/make/tools/src/build/tools/stripproperties/StripPropertiesCorba.java rename to corba/make/src/classes/build/tools/stripproperties/StripPropertiesCorba.java diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/Makefile b/corba/src/share/classes/com/sun/tools/corba/se/logutil/Makefile deleted file mode 100644 index 9fcb326b711..00000000000 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. 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/kenc/util - -CLASSES=LogWrapperBase IndentingPrintWriter StringUtil -SOURCE=$(CLASSES:%=$(PACKAGE)/%.java) -OBJECT=$(CLASSES:%=$(PACKAGE)/%.class) - -MCROOTS= Activation Interceptors IOR Naming ORBUtil POA Util OMG -MCFILES=$(MCROOTS:%=data/%.mc) -MCSOURCE=$(MCROOTS:%=$(PACKAGE)/%SystemException.java) -MCCLASS=$(MCROOTS:%=$(PACKAGE)/%SystemException.class) -MCRESOURCE=$(MCROOTS:%=resources/%SystemException.resource) - -JARDIR=lib -UTILJAR=$(JARDIR)/util.jar -JSCHEMEJAR=$(JARDIR)/jscheme.jar -JARS=$(UTILJAR):$(JSCHEMEJAR) - -all: mkdir jar resources classes - -mkdir : - @-mkdir resources - -clean: - @-rm $(OBJECT) $(MCSOURCE) $(MCOBJECT) $(MCCLASS) $(MCRESOURCE) $(UTILJAR) - -test: - @echo "PACKAGE :" $(PACKAGE) - @echo "CLASSES :" $(CLASSES) - @echo "SOURCE :" $(SOURCE) - @echo "OBJECT :" $(OBJECT) - @echo "MCROOTS :" $(MCROOTS) - @echo "MCFILES :" $(MCFILES) - @echo "MCCLASS :" $(MCCLASS) - @echo "MCRESOURCE :" $(MCRESOURCE) - -jar: $(UTILJAR) - -$(UTILJAR) : $(OBJECT) - jar cvf $(JARDIR)/util.jar $(OBJECT) - -$(OBJECT) : $(SOURCE) - -classes: $(MCCLASS) - -$(MCCLASS) : $(MCSOURCE) - -$(MCSOURCE) : $(MCFILES) - -resources: $(MCRESOURCE) - -$(MCRESOURCE) : $(MCFILES) - -# This target does not compile, because the generated source code requires -# com.sun.corba.se.impl.util.SUNVMCID, which would normally be built in the -# ee package. This should not be a problem once everything is merged into the -# workspace. -genclasses: $(MCCLASS) - -$(PACKAGE)/%SystemException.java : data/%.mc - ./mc make-class $< - mv *SystemException.java $(PACKAGE) - -resources/%SystemException.resource : data/%.mc - ./mc make-resource $< - mv *.resource resources - -$(PACKAGE)/%.class : $(PACKAGE)/%.java - javac -classpath $(JARS) $< From 83ba7f9076d3d9edc5779c89888727ef67b2382f Mon Sep 17 00:00:00 2001 From: Michael Fang Date: Tue, 17 Dec 2013 22:03:54 -0800 Subject: [PATCH 061/265] 8026741: jdk8 l10n resource file translation update 5 Reviewed-by: naoto, yhuang --- corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp b/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp index 25f662abd91..47ba5c633ff 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp +++ b/corba/src/share/classes/com/sun/tools/corba/se/idl/idl_ja.prp @@ -110,7 +110,7 @@ ParseException.badAbstract=%0 (\u884C%1): %2\u306Eforward\u5BA3\u8A00\u3068\u5B9 ParseException.badCustom=%0 (\u884C%1): forward\u5024\u5BA3\u8A00\u306Fcustom\u3068\u3057\u3066\u5BA3\u8A00\u3067\u304D\u307E\u305B\u3093\u3002\n%2\n%3 ParseException.badRepIDAlreadyAssigned=%0 (\u884C%1): \u578B%2\u306B\u306F\u3001\u524D\u306EID\u30D7\u30E9\u30B0\u30DE\u30FB\u30C7\u30A3\u30EC\u30AF\u30C6\u30A3\u30D6\u306E\u30EA\u30DD\u30B8\u30C8\u30EAID\u304C\u3059\u3067\u306B\u5272\u308A\u5F53\u3066\u3089\u308C\u3066\u3044\u307E\u3059\u3002\n%3\n%4 ParseException.badRepIDForm=%0 (\u884C%1): \u30EA\u30DD\u30B8\u30C8\u30EAID '%2'\u306E\u5F62\u5F0F\u306F':'\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n%3\n%4 -ParseException.badRepIDPrefix=%0 (\u884C%1): \u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9%2\u306B\u306F\u3001'%4'\u3067\u306F\u306A\u304F\u30EA\u30DD\u30B8\u30C8\u30EAID\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9`%3'\u304C\u5FC5\u8981\u3067\u3059\u3002\n%5\n%6 +ParseException.badRepIDPrefix=%0 (\u884C%1): \u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9%2\u306B\u306F\u3001'%4'\u3067\u306F\u306A\u304F\u30EA\u30DD\u30B8\u30C8\u30EAID\u63A5\u982D\u8F9E`%3'\u304C\u5FC5\u8981\u3067\u3059\u3002\n%5\n%6 ParseException.badState=%0 (\u884C%1): %2\u306F\u30B9\u30C6\u30FC\u30C8\u30D5\u30EB\u30FB\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306B\u3067\u304D\u307E\u305B\u3093\u3002\u8907\u6570\u306E\u30B9\u30C6\u30FC\u30C8\u30D5\u30EB\u89AA\u304C\u3042\u308A\u307E\u3059\u3002\n%3\n%4 ParseException.branchLabel=%0 (\u884C%1): case %2\u306F\u3059\u3067\u306B\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n%3\n%4 ParseException.branchName=%0 (\u884C%1): %2\u3068\u3044\u3046\u540D\u524D\u306E\u5206\u5C90\u306F\u3059\u3067\u306B\u5BA3\u8A00\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n%3\n%4 From 9c10079653848d68104f085a2d8cb80dd147a2cd Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 20 Dec 2013 13:51:14 +0100 Subject: [PATCH 062/265] 8030863: PPC64: (part 220): ConstantTableBase for calls between args and jvms Add ConstantTableBase node edge after parameters and before jvms. Adapt jvms offsets. Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/ppc.ad | 44 +++++++++++--------------- hotspot/src/share/vm/adlc/archDesc.cpp | 3 +- hotspot/src/share/vm/adlc/archDesc.hpp | 7 ++++ hotspot/src/share/vm/adlc/main.cpp | 1 + hotspot/src/share/vm/adlc/output_c.cpp | 25 +++++++++++---- hotspot/src/share/vm/adlc/output_h.cpp | 10 +++++- hotspot/src/share/vm/opto/callnode.cpp | 12 +++++++ hotspot/src/share/vm/opto/callnode.hpp | 13 ++++++-- hotspot/src/share/vm/opto/compile.hpp | 2 ++ hotspot/src/share/vm/opto/matcher.cpp | 16 ++++++++-- 10 files changed, 94 insertions(+), 39 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index cae2015bbab..03a86b2e51e 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -3563,9 +3563,6 @@ encode %{ // postalloc expand emitter for virtual calls. enc_class postalloc_expand_java_dynamic_call_sched(method meth, iRegLdst toc) %{ - // Toc is in return address field, though not accessible via postalloc_expand - // functionaliy. - Node *toc = in(TypeFunc::ReturnAdr); // Create the nodes for loading the IC from the TOC. loadConLNodesTuple loadConLNodes_IC = @@ -3592,23 +3589,21 @@ encode %{ // New call needs all inputs of old call. // Req... for (uint i = 0; i < req(); ++i) { - if (i != TypeFunc::ReturnAdr) { - call->add_req(in(i)); + // The expanded node does not need toc any more. + // Add the inline cache constant here instead. This expresses the + // register of the inline cache must be live at the call. + // Else we would have to adapt JVMState by -1. + if (i == mach_constant_base_node_input()) { + call->add_req(loadConLNodes_IC._last); } else { - // The expanded node does not need toc any more. - call->add_req(C->top()); + call->add_req(in(i)); } } // ...as well as prec - for (uint i = req(); i < len() ; ++i) { + for (uint i = req(); i < len(); ++i) { call->add_prec(in(i)); } - // The cache must come before the call, but it's not a req edge. - // GL: actually it should be a req edge to express that the - // register must be live in the Call. But as R19 is declared to be - // the inline_cache_reg that's fine. - call->add_prec(loadConLNodes_IC._last); // Remember nodes loading the inline cache into r19. call->_load_ic_hi_node = loadConLNodes_IC._large_hi; call->_load_ic_node = loadConLNodes_IC._small; @@ -3638,13 +3633,13 @@ encode %{ // Must be invalid_vtable_index, not nonvirtual_vtable_index. assert(_vtable_index == Method::invalid_vtable_index, "correct sentinel value"); Register ic_reg = as_Register(Matcher::inline_cache_reg_encode()); - AddressLiteral oop = __ allocate_metadata_address((Metadata *)Universe::non_oop_word()); + AddressLiteral meta = __ allocate_metadata_address((Metadata *)Universe::non_oop_word()); - address virtual_call_oop_addr = __ pc(); - __ load_const_from_method_toc(ic_reg, oop, Rtoc); + address virtual_call_meta_addr = __ pc(); + __ load_const_from_method_toc(ic_reg, meta, Rtoc); // CALL to fixup routine. Fixup routine uses ScopeDesc info // to determine who we intended to call. - __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr)); + __ relocate(virtual_call_Relocation::spec(virtual_call_meta_addr)); emit_call_with_trampoline_stub(_masm, (address)$meth$$method, relocInfo::none); assert(((MachCallDynamicJavaNode*)this)->ret_addr_offset() == __ offset() - start_offset, "Fix constant in ret_addr_offset()"); @@ -3674,6 +3669,7 @@ encode %{ "Fix constant in ret_addr_offset()"); } #endif + guarantee(0, "Fix handling of toc edge: messes up derived/base pairs."); Unimplemented(); // ret_addr_offset not yet fixed. Depends on compressed oops (load klass!). %} @@ -3775,16 +3771,14 @@ encode %{ // New call needs all inputs of old call. // Req... for (uint i = 0; i < req(); ++i) { - if (i != TypeFunc::ReturnAdr) { + if (i != mach_constant_base_node_input()) { call->add_req(in(i)); - } else { - // put the mtctr where ReturnAdr would be - call->add_req(mtctr); } } // These must be reqired edges, as the registers are live up to // the call. Else the constants are handled as kills. + call->add_req(mtctr); call->add_req(loadConLNodes_Env._last); call->add_req(loadConLNodes_Toc._last); @@ -3818,7 +3812,7 @@ frame %{ // These two registers define part of the calling convention between // compiled code and the interpreter. - // Inline Cache Register or methodOop for I2C. + // Inline Cache Register or method for I2C. inline_cache_reg(R19); // R19_method // Method Oop Register when calling interpreter. @@ -6149,8 +6143,8 @@ instruct loadConP_lo(iRegPdst dst, immP_NM src, iRegLdst base) %{ size(4); ins_encode %{ // TODO: PPC port $archOpcode(ppc64Opcode_ld); - int offset = ra_->C->in_scratch_emit_size() ? 0 : MacroAssembler::largeoffset_si16_si16_lo(_const_toc_offset_hi_node->_const_toc_offset); - __ ld($dst$$Register, offset, $base$$Register); + int offset = ra_->C->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; + __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); %} ins_pipe(pipe_class_memory); %} @@ -6784,7 +6778,7 @@ instruct cond_add_base(iRegPdst dst, flagsReg crx, iRegPsrc src1) %{ Label done; __ beq($crx$$CondRegister, done); __ add($dst$$Register, $src1$$Register, R30); - // TODO PPC port __ endgroup_if_needed(_size == 12); + // TODO PPC port __ endgroup_if_needed(_size == 12); __ bind(done); %} ins_pipe(pipe_class_default); diff --git a/hotspot/src/share/vm/adlc/archDesc.cpp b/hotspot/src/share/vm/adlc/archDesc.cpp index fd60e25acb7..37f5cb227b1 100644 --- a/hotspot/src/share/vm/adlc/archDesc.cpp +++ b/hotspot/src/share/vm/adlc/archDesc.cpp @@ -172,7 +172,8 @@ ArchDesc::ArchDesc() _internalOps(cmpstr,hashstr, Form::arena), _internalMatch(cmpstr,hashstr, Form::arena), _chainRules(cmpstr,hashstr, Form::arena), - _cisc_spill_operand(NULL) { + _cisc_spill_operand(NULL), + _needs_clone_jvms(false) { // Initialize the opcode to MatchList table with NULLs for( int i=0; i<_last_opcode; ++i ) { diff --git a/hotspot/src/share/vm/adlc/archDesc.hpp b/hotspot/src/share/vm/adlc/archDesc.hpp index 94c7a50fd33..fb8322a0cbe 100644 --- a/hotspot/src/share/vm/adlc/archDesc.hpp +++ b/hotspot/src/share/vm/adlc/archDesc.hpp @@ -121,6 +121,12 @@ private: // to access [stack_pointer + offset] OperandForm *_cisc_spill_operand; + // If a Call node uses $constanttablebase, it gets MachConstantBaseNode + // by the matcher and the matcher will modify the jvms. If so, jvm states + // always have to be cloned when a node is cloned. Adlc generates + // Compile::needs_clone_jvms() accordingly. + bool _needs_clone_jvms; + // Methods for outputting the DFA void gen_match(FILE *fp, MatchList &mlist, ProductionState &status, Dict &operands_chained_from); void chain_rule(FILE *fp, const char *indent, const char *ideal, @@ -289,6 +295,7 @@ public: void addPreHeaderBlocks(FILE *fp_hpp); void addHeaderBlocks(FILE *fp_hpp); void addSourceBlocks(FILE *fp_cpp); + void generate_needs_clone_jvms(FILE *fp_cpp); void generate_adlc_verification(FILE *fp_cpp); // output declaration of class State diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index 612d0e582d9..9c558a5f564 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.cpp @@ -306,6 +306,7 @@ int main(int argc, char *argv[]) AD.buildInstructMatchCheck(AD._CPP_file._fp); // .cpp // define methods for machine dependent frame management AD.buildFrameMethods(AD._CPP_file._fp); // .cpp + AD.generate_needs_clone_jvms(AD._CPP_file._fp); // do this last: AD.addPreprocessorChecks(AD._CPP_file._fp); // .cpp diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index d12d0378411..eae289cb1c8 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1842,17 +1842,23 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { // There are nodes that don't use $constantablebase, but still require that it // is an input to the node. Example: divF_reg_immN, Repl32B_imm on x86_64. if (node->is_mach_constant() || node->needs_constant_base()) { - fprintf(fp," add_req(C->mach_constant_base_node());\n"); + if (node->is_ideal_call() != Form::invalid_type && + node->is_ideal_call() != Form::JAVA_LEAF) { + fprintf(fp, " // MachConstantBaseNode added in matcher.\n"); + _needs_clone_jvms = true; + } else { + fprintf(fp, " add_req(C->mach_constant_base_node());\n"); + } } - fprintf(fp,"\n"); - if( node->expands() ) { - fprintf(fp," return result;\n"); + fprintf(fp, "\n"); + if (node->expands()) { + fprintf(fp, " return result;\n"); } else { - fprintf(fp," return this;\n"); + fprintf(fp, " return this;\n"); } - fprintf(fp,"}\n"); - fprintf(fp,"\n"); + fprintf(fp, "}\n"); + fprintf(fp, "\n"); } @@ -3642,6 +3648,11 @@ char reg_save_policy(const char *calling_convention) { return callconv; } +void ArchDesc::generate_needs_clone_jvms(FILE *fp_cpp) { + fprintf(fp_cpp, "bool Compile::needs_clone_jvms() { return %s; }\n\n", + _needs_clone_jvms ? "true" : "false"); +} + //---------------------------generate_assertion_checks------------------- void ArchDesc::generate_adlc_verification(FILE *fp_cpp) { fprintf(fp_cpp, "\n"); diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index fa9b79a172a..052f2ccfbab 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -1665,7 +1665,15 @@ void ArchDesc::declareClasses(FILE *fp) { if (instr->needs_constant_base() && !instr->is_mach_constant()) { // These inherit the funcion from MachConstantNode. - fprintf(fp," virtual uint mach_constant_base_node_input() const { return req()-1; }\n"); + fprintf(fp," virtual uint mach_constant_base_node_input() const { "); + if (instr->is_ideal_call() != Form::invalid_type && + instr->is_ideal_call() != Form::JAVA_LEAF) { + // MachConstantBase goes behind arguments, but before jvms. + fprintf(fp,"assert(tf() && tf()->domain(), \"\"); return tf()->domain()->cnt();"); + } else { + fprintf(fp,"return req()-1;"); + } + fprintf(fp," }\n"); } // Allow machine-independent optimization, invert the sense of the IF test diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 12dcf38b0f2..4289acd9696 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -595,6 +595,18 @@ void JVMState::set_map_deep(SafePointNode* map) { } } +// Adapt offsets in in-array after adding or removing an edge. +// Prerequisite is that the JVMState is used by only one node. +void JVMState::adapt_position(int delta) { + for (JVMState* jvms = this; jvms != NULL; jvms = jvms->caller()) { + jvms->set_locoff(jvms->locoff() + delta); + jvms->set_stkoff(jvms->stkoff() + delta); + jvms->set_monoff(jvms->monoff() + delta); + jvms->set_scloff(jvms->scloff() + delta); + jvms->set_endoff(jvms->endoff() + delta); + } +} + //============================================================================= uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index 699f7e7d0fd..0d9e469a128 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -299,6 +299,7 @@ public: JVMState* clone_deep(Compile* C) const; // recursively clones caller chain JVMState* clone_shallow(Compile* C) const; // retains uncloned caller void set_map_deep(SafePointNode *map);// reset map for all callers + void adapt_position(int delta); // Adapt offsets in in-array after adding an edge. #ifndef PRODUCT void format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const; @@ -559,9 +560,15 @@ public: // Are we guaranteed that this node is a safepoint? Not true for leaf calls and // for some macro nodes whose expansion does not have a safepoint on the fast path. virtual bool guaranteed_safepoint() { return true; } - // For macro nodes, the JVMState gets modified during expansion, so when cloning - // the node the JVMState must be cloned. - virtual void clone_jvms(Compile* C) { } // default is not to clone + // For macro nodes, the JVMState gets modified during expansion. If calls + // use MachConstantBase, it gets modified during matching. So when cloning + // the node the JVMState must be cloned. Default is not to clone. + virtual void clone_jvms(Compile* C) { + if (C->needs_clone_jvms() && jvms() != NULL) { + set_jvms(jvms()->clone_deep(C)); + jvms()->set_map_deep(this); + } + } // Returns true if the call may modify n virtual bool may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase); diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 2d073a9e008..de33b0678b5 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -758,6 +758,8 @@ class Compile : public Phase { MachConstantBaseNode* mach_constant_base_node(); bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; } + // Generated by adlc, true if CallNode requires MachConstantBase. + bool needs_clone_jvms(); // Handy undefined Node Node* top() const { return _top; } diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 311bd249335..6d35afde069 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1338,12 +1338,24 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { } // Debug inputs begin just after the last incoming parameter - assert( (mcall == NULL) || (mcall->jvms() == NULL) || - (mcall->jvms()->debug_start() + mcall->_jvmadj == mcall->tf()->domain()->cnt()), "" ); + 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 + // ins are not complete then. + msfpt->ins_req(msfpt->mach_constant_base_node_input(), C->mach_constant_base_node()); + if (msfpt->jvms() && + msfpt->mach_constant_base_node_input() <= msfpt->jvms()->debug_start() + msfpt->_jvmadj) { + // We added an edge before jvms, so we must adapt the position of the ins. + msfpt->jvms()->adapt_position(+1); + } + } + // Registers killed by the call are set in the local scheduling pass // of Global Code Motion. return msfpt; From fe000cd966d93cb7fe8d75fed5dcf7e1dbbac61e Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 6 Jan 2014 11:02:21 +0100 Subject: [PATCH 063/265] 8031188: Fix for 8029015: PPC64 (part 216): opto: trap based null and range checks Swap the Projs in the block list so that the new block is added behind the proper node. Reviewed-by: kvn --- hotspot/src/share/vm/opto/block.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 9d2f9522bed..2553545a726 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -748,6 +748,11 @@ Block *PhaseCFG::fixup_trap_based_check(Node *branch, Block *block, int block_po block->_succs.map(0, get_block_for_node(proj_never ->raw_out(0))); // The target of the trap. block->_succs.map(1, get_block_for_node(proj_always->raw_out(0))); // The fall through target. + if (block->get_node(block->number_of_nodes() - block->_num_succs + 1) != proj_always) { + block->map_node(proj_never, block->number_of_nodes() - block->_num_succs + 0); + block->map_node(proj_always, block->number_of_nodes() - block->_num_succs + 1); + } + // Place the fall through block after this block. Block *bs1 = block->non_connector_successor(1); if (bs1 != bnext && move_to_next(bs1, block_pos)) { From 06b9210700498de01a502549e7c6165837b410b4 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Tue, 7 Jan 2014 17:24:59 +0100 Subject: [PATCH 064/265] 8031319: PPC64: Some fixes in ppc and aix coding Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp | 2 + hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 42 ++--- hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp | 6 +- hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 2 +- hotspot/src/cpu/ppc/vm/ppc.ad | 20 +-- hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 6 +- hotspot/src/os/aix/vm/os_aix.cpp | 120 +++++++++++--- .../aix_ppc/vm/atomic_aix_ppc.inline.hpp | 150 +++++++++--------- 8 files changed, 217 insertions(+), 131 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp index 3095ccd98b6..c9853c589cc 100644 --- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp @@ -1513,6 +1513,7 @@ address CppInterpreterGenerator::generate_native_entry(void) { // Resize frame to get rid of a potential extension. __ resize_frame_to_initial_caller(R11_scratch1, R12_scratch2); + assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order"); // Load target address of the runtime stub. __ load_const(R12_scratch2, (StubRoutines::throw_StackOverflowError_entry())); __ mtctr(R12_scratch2); @@ -2150,6 +2151,7 @@ address CppInterpreterGenerator::generate_normal_entry(void) { // Since we restored the caller SP above, the rethrow_excp_entry can restore the original interpreter state // registers using the stack and resume the calling method with a pending excp. + assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order"); __ load_const(R3_ARG1, (StubRoutines::throw_StackOverflowError_entry())); __ mtctr(R3_ARG1); __ bctr(); diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 80a53fc9afb..dfe97adadb5 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -206,7 +206,7 @@ int MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop dat // The relocation points to the second instruction, the ori, // and the ori reads and writes the same register dst. const int dst = inv_rta_field(inst2); - assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be addi reading and writing dst"); + assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be ori reading and writing dst"); // Now, find the preceding addis which writes to dst. int inst1 = 0; address inst1_addr = inst2_addr - BytesPerInstWord; @@ -222,8 +222,7 @@ int MacroAssembler::patch_set_narrow_oop(address a, address bound, narrowOop dat int xd = (data >> 0) & 0xffff; set_imm((int *)inst1_addr, (short)(xc)); // see enc_load_con_narrow_hi/_lo - set_imm((int *)inst2_addr, (short)(xd)); - + set_imm((int *)inst2_addr, (xd)); // unsigned int return (int)((intptr_t)inst2_addr - (intptr_t)inst1_addr); } @@ -237,7 +236,7 @@ narrowOop MacroAssembler::get_narrow_oop(address a, address bound) { // The relocation points to the second instruction, the ori, // and the ori reads and writes the same register dst. const int dst = inv_rta_field(inst2); - assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be addi reading and writing dst"); + assert(is_ori(inst2) && inv_rs_field(inst2) == dst, "must be ori reading and writing dst"); // Now, find the preceding lis which writes to dst. int inst1 = 0; address inst1_addr = inst2_addr - BytesPerInstWord; @@ -996,10 +995,10 @@ address MacroAssembler::call_c(const FunctionDescriptor* fd, relocInfo::relocTyp bool has_env = (fd != NULL && fd->env() != NULL); return branch_to(R11, /*and_link=*/true, - /*save toc=*/false, - /*restore toc=*/false, - /*load toc=*/true, - /*load env=*/has_env); + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/has_env); } else { // It's a friend function. Load the entry point and don't care about // toc and env. Use an optimizable call instruction, but ensure the @@ -1020,10 +1019,10 @@ address MacroAssembler::call_c(const FunctionDescriptor* fd, relocInfo::relocTyp // so do a full call-c here. load_const(R11, (address)fd, R0); return branch_to(R11, /*and_link=*/true, - /*save toc=*/false, - /*restore toc=*/false, - /*load toc=*/true, - /*load env=*/true); + /*save toc=*/false, + /*restore toc=*/false, + /*load toc=*/true, + /*load env=*/true); } else { // it's a friend function, load the entry point and don't care about // toc and env. @@ -1967,12 +1966,13 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Must fence, otherwise, preceding store(s) may float below cmpxchg. // Compare object markOop with mark and if equal exchange scratch1 with object markOop. // CmpxchgX sets cr_reg to cmpX(current, displaced). + membar(Assembler::StoreStore); cmpxchgd(/*flag=*/flag, /*current_value=*/current_header, /*compare_value=*/displaced_header, /*exchange_value=*/box, /*where=*/oop, - MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_acquire_lock(), noreg, &cas_failed); @@ -2158,7 +2158,7 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base, Register Rtmp, Regis load_const_optimized(Rtmp, (address)byte_map_base, R0); srdi(Robj, Robj, CardTableModRefBS::card_shift); li(R0, 0); // dirty - if (UseConcMarkSweepGC) release(); + if (UseConcMarkSweepGC) membar(Assembler::StoreStore); stbx(R0, Rtmp, Robj); } @@ -2399,15 +2399,17 @@ void MacroAssembler::get_vm_result_2(Register metadata_result) { void MacroAssembler::encode_klass_not_null(Register dst, Register src) { - if (src == noreg) src = dst; + Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided. if (Universe::narrow_klass_base() != 0) { - load_const(R0, Universe::narrow_klass_base()); - sub(dst, src, R0); + load_const(R0, Universe::narrow_klass_base(), (dst != current) ? dst : noreg); // Use dst as temp if it is free. + sub(dst, current, R0); + current = dst; } - if (Universe::narrow_klass_shift() != 0 || - Universe::narrow_klass_base() == 0 && src != dst) { // Move required. - srdi(dst, src, Universe::narrow_klass_shift()); + if (Universe::narrow_klass_shift() != 0) { + srdi(dst, current, Universe::narrow_klass_shift()); + current = dst; } + mr_if_needed(dst, current); // Move may be required. } void MacroAssembler::store_klass(Register dst_oop, Register klass, Register ck) { diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp index 434ec7c3893..f6249450de1 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp @@ -71,7 +71,7 @@ address NativeCall::destination() const { if (nm->stub_contains(destination) && is_NativeCallTrampolineStub_at(destination)) { // Yes we do, so get the destination from the trampoline stub. const address trampoline_stub_addr = destination; - destination = NativeCallTrampolineStub_at(trampoline_stub_addr)->destination(); + destination = NativeCallTrampolineStub_at(trampoline_stub_addr)->destination(nm); } return destination; @@ -371,8 +371,8 @@ address NativeCallTrampolineStub::encoded_destination_addr() const { return instruction_addr; } -address NativeCallTrampolineStub::destination() const { - CodeBlob* cb = CodeCache::find_blob(addr_at(0)); +address NativeCallTrampolineStub::destination(nmethod *nm) const { + CodeBlob* cb = nm ? nm : CodeCache::find_blob_unsafe(addr_at(0)); address ctable = cb->content_begin(); return *(address*)(ctable + destination_toc_offset()); diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index 6c7db6d25b2..0ef57be0556 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -378,7 +378,7 @@ class NativeCallTrampolineStub : public NativeInstruction { public: - address destination() const; + address destination(nmethod *nm = NULL) const; int destination_toc_offset() const; void set_destination(address new_destination); diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 03a86b2e51e..173d5445139 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -634,7 +634,6 @@ reg_class bits64_reg_leaf_call( R31_H, R31 ); -// 64 bit registers used excluding r19. // Used to hold the TOC to avoid collisions with expanded DynamicCall // which uses r19 as inline cache internally and expanded LeafCall which uses // r2, r11 and r12 internally. @@ -1421,13 +1420,11 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { // Optimized version for most common case. if (UsePower6SchedulerPPC64 && - !method_is_frameless && Assembler::is_simm((int)(-(_abi(lr) + offset)), 16) && + !method_is_frameless && Assembler::is_simm((int)(-offset), 16) && !(false /* ConstantsALot TODO: PPC port*/)) { ___(or) mr(callers_sp, R1_SP); - ___(addi) addi(R1_SP, R1_SP, -offset); - ___stop; // Emulator won't recognize dependency. - ___(std) std(return_pc, _abi(lr) + offset, R1_SP); - ___(std) std(callers_sp, 0, R1_SP); + ___(std) std(return_pc, _abi(lr), R1_SP); + ___(stdu) stdu(R1_SP, -offset, R1_SP); return; } @@ -1472,6 +1469,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } #undef ___ #undef ___stop +#undef ___advance uint MachPrologNode::size(PhaseRegAlloc *ra_) const { // Variable size. determine dynamically. @@ -2853,7 +2851,7 @@ encode %{ // StoreStore barrier conditionally. __ lwz(R0, 0, $releaseFieldAddr$$Register); __ cmpwi(CCR0, R0, 0); - __ beq_predict_taken(CCR0, skip_release); + __ beq_predict_taken(CCR0, skip_storestore); #endif __ li(R0, 0); __ membar(Assembler::StoreStore); @@ -3518,8 +3516,9 @@ encode %{ #endif // If fails should store backlink before unextending. - if (ra_->C->env()->failing()) + if (ra_->C->env()->failing()) { return; + } %} // Second node of expanded dynamic call - the call. @@ -3940,11 +3939,6 @@ ins_attrib ins_cost(DEFAULT_COST); // long branch? Not required. ins_attrib ins_short_branch(0); -// This instruction does implicit checks at the given machine-instruction offset -// (optional attribute). -ins_attrib ins_implicit_check_offset(-1); // TODO: PPC port - -ins_attrib ins_implicit_check_follows_matched_true_path(true); ins_attrib ins_is_TrapBasedCheckNode(true); // Number of constants. diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index c9a4538454a..0fc3491531c 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -2027,6 +2027,11 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_forward_exception_entry = generate_forward_exception(); StubRoutines::_call_stub_entry = generate_call_stub(StubRoutines::_call_stub_return_address); StubRoutines::_catch_exception_entry = generate_catch_exception(); + + // Build this early so it's available for the interpreter. + StubRoutines::_throw_StackOverflowError_entry = + generate_throw_exception("StackOverflowError throw_exception", + CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); } void generate_all() { @@ -2038,7 +2043,6 @@ class StubGenerator: public StubCodeGenerator { // Handle IncompatibleClassChangeError in itable stubs. StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 049f32242c0..2b0310d8410 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1152,8 +1152,19 @@ void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { bool os::getTimesSecs(double* process_real_time, double* process_user_time, double* process_system_time) { - Unimplemented(); - return false; + struct tms ticks; + clock_t real_ticks = times(&ticks); + + if (real_ticks == (clock_t) (-1)) { + return false; + } else { + double ticks_per_second = (double) clock_tics_per_sec; + *process_user_time = ((double) ticks.tms_utime) / ticks_per_second; + *process_system_time = ((double) ticks.tms_stime) / ticks_per_second; + *process_real_time = ((double) real_ticks) / ticks_per_second; + + return true; + } } @@ -2440,7 +2451,7 @@ cleanup_shm: // trace if (Verbose && !addr) { if (requested_addr != NULL) { - warning("failed to shm-allocate 0x%llX bytes at with address 0x%p.", size, requested_addr); + warning("failed to shm-allocate 0x%llX bytes at wish address 0x%p.", size, requested_addr); } else { warning("failed to shm-allocate 0x%llX bytes at any address.", size); } @@ -2521,16 +2532,17 @@ static char* reserve_mmaped_memory(size_t bytes, char* requested_addr) { cleanup_mmap: - if (addr) { - if (Verbose) { + // trace + if (Verbose) { + if (addr) { fprintf(stderr, "mmap-allocated 0x%p .. 0x%p (0x%llX bytes)\n", addr, addr + bytes, bytes); } - } - else { - if (requested_addr != NULL) { - warning("failed to mmap-allocate 0x%llX bytes at wish address 0x%p.", bytes, requested_addr); - } else { - warning("failed to mmap-allocate 0x%llX bytes at any address.", bytes); + else { + if (requested_addr != NULL) { + warning("failed to mmap-allocate 0x%llX bytes at wish address 0x%p.", bytes, requested_addr); + } else { + warning("failed to mmap-allocate 0x%llX bytes at any address.", bytes); + } } } @@ -3359,7 +3371,46 @@ struct sigaction* os::Aix::get_chained_signal_action(int sig) { static bool call_chained_handler(struct sigaction *actp, int sig, siginfo_t *siginfo, void *context) { - Unimplemented(); + // Call the old signal handler + if (actp->sa_handler == SIG_DFL) { + // It's more reasonable to let jvm treat it as an unexpected exception + // instead of taking the default action. + return false; + } else if (actp->sa_handler != SIG_IGN) { + if ((actp->sa_flags & SA_NODEFER) == 0) { + // automaticlly block the signal + sigaddset(&(actp->sa_mask), sig); + } + + sa_handler_t hand = NULL; + sa_sigaction_t sa = NULL; + bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0; + // retrieve the chained handler + if (siginfo_flag_set) { + sa = actp->sa_sigaction; + } else { + hand = actp->sa_handler; + } + + if ((actp->sa_flags & SA_RESETHAND) != 0) { + actp->sa_handler = SIG_DFL; + } + + // try to honor the signal mask + sigset_t oset; + pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset); + + // call into the chained handler + if (siginfo_flag_set) { + (*sa)(sig, siginfo, context); + } else { + (*hand)(sig); + } + + // restore the signal mask + pthread_sigmask(SIG_SETMASK, &oset, 0); + } + // Tell jvm's signal handler the signal is taken care of. return true; } @@ -4041,7 +4092,23 @@ static address same_page(address x, address y) { } bool os::find(address addr, outputStream* st) { - Unimplemented(); + + st->print(PTR_FORMAT ": ", addr); + + const LoadedLibraryModule* lib = LoadedLibraries::find_for_text_address(addr); + if (lib) { + lib->print(st); + return true; + } else { + lib = LoadedLibraries::find_for_data_address(addr); + if (lib) { + lib->print(st); + return true; + } else { + st->print_cr("(outside any module)"); + } + } + return false; } @@ -4099,8 +4166,22 @@ bool os::check_heap(bool force) { // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { - Unimplemented(); - return false; + DIR *dir = NULL; + struct dirent *ptr; + + dir = opendir(path); + if (dir == NULL) return true; + + /* Scan the directory */ + bool result = true; + char buf[sizeof(struct dirent) + MAX_PATH]; + while (result && (ptr = ::readdir(dir)) != NULL) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { + result = false; + } + } + closedir(dir); + return result; } // This code originates from JDK's sysOpen and open64_w @@ -4127,7 +4208,7 @@ int os::open(const char *path, int oflag, int mode) { fd = ::open64(path, oflag, mode); if (fd == -1) return -1; - //If the open succeeded, the file might still be a directory + // If the open succeeded, the file might still be a directory. { struct stat64 buf64; int ret = ::fstat64(fd, &buf64); @@ -4182,8 +4263,11 @@ int os::open(const char *path, int oflag, int mode) { // create binary file, rewriting existing file if required int os::create_binary_file(const char* path, bool rewrite_existing) { - Unimplemented(); - return 0; + int oflags = O_WRONLY | O_CREAT; + if (!rewrite_existing) { + oflags |= O_EXCL; + } + return ::open64(path, oflags, S_IREAD | S_IWRITE); } // return current position of file pointer diff --git a/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp index c7f8a26163f..86ade8265e2 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp @@ -53,62 +53,62 @@ inline void Atomic::store_ptr(void* store_value, volatile void* dest) { * inline jlong Atomic::load(volatile jlong* src) { return *src; } -/* - machine barrier instructions: +// +// machine barrier instructions: +// +// - ppc_sync two-way memory barrier, aka fence +// - ppc_lwsync orders Store|Store, +// Load|Store, +// Load|Load, +// but not Store|Load +// - ppc_eieio orders memory accesses for device memory (only) +// - ppc_isync invalidates speculatively executed instructions +// From the POWER ISA 2.06 documentation: +// "[...] an isync instruction prevents the execution of +// instructions following the isync until instructions +// preceding the isync have completed, [...]" +// From IBM's AIX assembler reference: +// "The isync [...] instructions causes the processor to +// refetch any instructions that might have been fetched +// prior to the isync instruction. The instruction isync +// causes the processor to wait for all previous instructions +// to complete. Then any instructions already fetched are +// discarded and instruction processing continues in the +// environment established by the previous instructions." +// +// semantic barrier instructions: +// (as defined in orderAccess.hpp) +// +// - ppc_release orders Store|Store, (maps to ppc_lwsync) +// Load|Store +// - ppc_acquire orders Load|Store, (maps to ppc_lwsync) +// Load|Load +// - ppc_fence orders Store|Store, (maps to ppc_sync) +// Load|Store, +// Load|Load, +// Store|Load +// - - ppc_sync two-way memory barrier, aka fence - - ppc_lwsync orders Store|Store, - Load|Store, - Load|Load, - but not Store|Load - - ppc_eieio orders memory accesses for device memory (only) - - ppc_isync invalidates speculatively executed instructions - From the POWER ISA 2.06 documentation: - "[...] an isync instruction prevents the execution of - instructions following the isync until instructions - preceding the isync have completed, [...]" - From IBM's AIX assembler reference: - "The isync [...] instructions causes the processor to - refetch any instructions that might have been fetched - prior to the isync instruction. The instruction isync - causes the processor to wait for all previous instructions - to complete. Then any instructions already fetched are - discarded and instruction processing continues in the - environment established by the previous instructions." - - semantic barrier instructions: - (as defined in orderAccess.hpp) - - - ppc_release orders Store|Store, (maps to ppc_lwsync) - Load|Store - - ppc_acquire orders Load|Store, (maps to ppc_lwsync) - Load|Load - - ppc_fence orders Store|Store, (maps to ppc_sync) - Load|Store, - Load|Load, - Store|Load -*/ - -#define strasm_ppc_sync "\n sync \n" -#define strasm_ppc_lwsync "\n lwsync \n" -#define strasm_ppc_isync "\n isync \n" -#define strasm_ppc_release strasm_ppc_lwsync -#define strasm_ppc_acquire strasm_ppc_lwsync -#define strasm_ppc_fence strasm_ppc_sync -#define strasm_ppc_nobarrier "" -#define strasm_ppc_nobarrier_clobber_memory "" +#define strasm_sync "\n sync \n" +#define strasm_lwsync "\n lwsync \n" +#define strasm_isync "\n isync \n" +#define strasm_release strasm_lwsync +#define strasm_acquire strasm_lwsync +#define strasm_fence strasm_sync +#define strasm_nobarrier "" +#define strasm_nobarrier_clobber_memory "" inline jint Atomic::add (jint add_value, volatile jint* dest) { unsigned int result; __asm__ __volatile__ ( - strasm_ppc_lwsync + strasm_lwsync "1: lwarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stwcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_isync + strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); @@ -122,12 +122,12 @@ inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { long result; __asm__ __volatile__ ( - strasm_ppc_lwsync + strasm_lwsync "1: ldarx %0, 0, %2 \n" " add %0, %0, %1 \n" " stdcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_isync + strasm_isync : /*%0*/"=&r" (result) : /*%1*/"r" (add_value), /*%2*/"r" (dest) : "cc", "memory" ); @@ -145,15 +145,15 @@ inline void Atomic::inc (volatile jint* dest) { unsigned int temp; __asm__ __volatile__ ( - strasm_ppc_nobarrier + strasm_nobarrier "1: lwarx %0, 0, %2 \n" " addic %0, %0, 1 \n" " stwcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_nobarrier + strasm_nobarrier : /*%0*/"=&r" (temp), "=m" (*dest) : /*%2*/"r" (dest), "m" (*dest) - : "cc" strasm_ppc_nobarrier_clobber_memory); + : "cc" strasm_nobarrier_clobber_memory); } @@ -162,15 +162,15 @@ inline void Atomic::inc_ptr(volatile intptr_t* dest) { long temp; __asm__ __volatile__ ( - strasm_ppc_nobarrier + strasm_nobarrier "1: ldarx %0, 0, %2 \n" " addic %0, %0, 1 \n" " stdcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_nobarrier + strasm_nobarrier : /*%0*/"=&r" (temp), "=m" (*dest) : /*%2*/"r" (dest), "m" (*dest) - : "cc" strasm_ppc_nobarrier_clobber_memory); + : "cc" strasm_nobarrier_clobber_memory); } @@ -184,15 +184,15 @@ inline void Atomic::dec (volatile jint* dest) { unsigned int temp; __asm__ __volatile__ ( - strasm_ppc_nobarrier + strasm_nobarrier "1: lwarx %0, 0, %2 \n" " addic %0, %0, -1 \n" " stwcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_nobarrier + strasm_nobarrier : /*%0*/"=&r" (temp), "=m" (*dest) : /*%2*/"r" (dest), "m" (*dest) - : "cc" strasm_ppc_nobarrier_clobber_memory); + : "cc" strasm_nobarrier_clobber_memory); } @@ -201,15 +201,15 @@ inline void Atomic::dec_ptr(volatile intptr_t* dest) { long temp; __asm__ __volatile__ ( - strasm_ppc_nobarrier + strasm_nobarrier "1: ldarx %0, 0, %2 \n" " addic %0, %0, -1 \n" " stdcx. %0, 0, %2 \n" " bne- 1b \n" - strasm_ppc_nobarrier + strasm_nobarrier : /*%0*/"=&r" (temp), "=m" (*dest) : /*%2*/"r" (dest), "m" (*dest) - : "cc" strasm_ppc_nobarrier_clobber_memory); + : "cc" strasm_nobarrier_clobber_memory); } @@ -227,14 +227,14 @@ inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) { __asm__ __volatile__ ( /* lwsync */ - strasm_ppc_lwsync + strasm_lwsync /* atomic loop */ "1: \n" " lwarx %[old_value], %[dest], %[zero] \n" " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" /* isync */ - strasm_ppc_sync + strasm_sync /* exit */ "2: \n" /* out */ @@ -263,14 +263,14 @@ inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des __asm__ __volatile__ ( /* lwsync */ - strasm_ppc_lwsync + strasm_lwsync /* atomic loop */ "1: \n" " ldarx %[old_value], %[dest], %[zero] \n" " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" /* isync */ - strasm_ppc_sync + strasm_sync /* exit */ "2: \n" /* out */ @@ -304,7 +304,7 @@ inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compa __asm__ __volatile__ ( /* fence */ - strasm_ppc_sync + strasm_sync /* simple guard */ " lwz %[old_value], 0(%[dest]) \n" " cmpw %[compare_value], %[old_value] \n" @@ -317,7 +317,7 @@ inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compa " stwcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" /* acquire */ - strasm_ppc_sync + strasm_sync /* exit */ "2: \n" /* out */ @@ -348,7 +348,7 @@ inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong c __asm__ __volatile__ ( /* fence */ - strasm_ppc_sync + strasm_sync /* simple guard */ " ld %[old_value], 0(%[dest]) \n" " cmpd %[compare_value], %[old_value] \n" @@ -361,7 +361,7 @@ inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong c " stdcx. %[exchange_value], %[dest], %[zero] \n" " bne- 1b \n" /* acquire */ - strasm_ppc_sync + strasm_sync /* exit */ "2: \n" /* out */ @@ -389,13 +389,13 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); } -#undef strasm_ppc_sync -#undef strasm_ppc_lwsync -#undef strasm_ppc_isync -#undef strasm_ppc_release -#undef strasm_ppc_acquire -#undef strasm_ppc_fence -#undef strasm_ppc_nobarrier -#undef strasm_ppc_nobarrier_clobber_memory +#undef strasm_sync +#undef strasm_lwsync +#undef strasm_isync +#undef strasm_release +#undef strasm_acquire +#undef strasm_fence +#undef strasm_nobarrier +#undef strasm_nobarrier_clobber_memory #endif // OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP From 2c63929e0827764aa9251883aa1f2e37e93b07b7 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 6 Feb 2014 14:57:02 +0000 Subject: [PATCH 065/265] 8033366: Add configure option to allow RMIConnector IIOP transport be selected compiled in or not Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 23 ++++++++++++++++++++++- common/autoconf/jdk-options.m4 | 13 +++++++++++++ common/autoconf/spec.gmk.in | 3 +++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index a03ee5cdb85..d27d204fa84 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -821,6 +821,7 @@ JDK_MINOR_VERSION JDK_MAJOR_VERSION USER_RELEASE_SUFFIX COMPRESS_JARS +RMICONNECTOR_IIOP UNLIMITED_CRYPTO CACERTS_FILE TEST_IN_BUILD @@ -1029,6 +1030,7 @@ enable_headful enable_hotspot_test_in_build with_cacerts_file enable_unlimited_crypto +enable_rmiconnector_iiop with_milestone with_update_version with_user_release_suffix @@ -1807,6 +1809,9 @@ Optional Features: run the Queens test after Hotspot build [disabled] --enable-unlimited-crypto Enable unlimited crypto policy [disabled] + --enable-rmiconnector-iiop + enable the JMX RMIConnector iiop transport + [disabled] --disable-debug-symbols disable generation of debug symbols [enabled] --disable-zip-debug-info disable zipping of debug-info files [enabled] @@ -4087,7 +4092,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1391160222 +DATE_WHEN_GENERATED=1391175012 ############################################################################### # @@ -19373,6 +19378,22 @@ fi # + ############################################################################### + # + # --enable-rmiconnector-iiop + # + # Check whether --enable-rmiconnector-iiop was given. +if test "${enable_rmiconnector_iiop+set}" = set; then : + enableval=$enable_rmiconnector_iiop; +fi + + if test "x$enable_rmiconnector_iiop" = "xyes"; then + RMICONNECTOR_IIOP=true + else + RMICONNECTOR_IIOP=false + fi + + ############################################################################### # # Compress jars diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 095fa79bf9a..44563af163f 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -424,6 +424,19 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], AC_SUBST(ENABLE_INTREE_EC) ]) + ############################################################################### + # + # --enable-rmiconnector-iiop + # + AC_ARG_ENABLE(rmiconnector-iiop, [AS_HELP_STRING([--enable-rmiconnector-iiop], + [enable the JMX RMIConnector iiop transport @<:@disabled@:>@])]) + if test "x$enable_rmiconnector_iiop" = "xyes"; then + RMICONNECTOR_IIOP=true + else + RMICONNECTOR_IIOP=false + fi + AC_SUBST(RMICONNECTOR_IIOP) + ############################################################################### # # Compress jars diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index ee18cb1b07a..3ba5d5a2d8d 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -286,6 +286,9 @@ CACERTS_FILE=@CACERTS_FILE@ # Enable unlimited crypto policy UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@ +# Enable RMIConnector IIOP transport +RMICONNECTOR_IIOP=@RMICONNECTOR_IIOP@ + # Necessary additional compiler flags to compile X11 X_CFLAGS:=@X_CFLAGS@ X_LIBS:=@X_LIBS@ From 350c12ac44a2ee5dffb3f5ea36a2e7588db3bd7b Mon Sep 17 00:00:00 2001 From: Jessica Man Date: Fri, 7 Feb 2014 13:31:16 +0100 Subject: [PATCH 066/265] 8033921: Build fails if --with-alsa option is used due to incorrect ALSA link parameter in autoconf script Reviewed-by: ihse, erikj --- common/autoconf/generated-configure.sh | 6 +++--- common/autoconf/libraries.m4 | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index d27d204fa84..849e4746005 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4092,7 +4092,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1391175012 +DATE_WHEN_GENERATED=1391775920 ############################################################################### # @@ -46779,7 +46779,7 @@ $as_echo "$as_me: WARNING: alsa not used, so --with-alsa is ignored" >&2;} fi if test "x${with_alsa}" != x; then - ALSA_LIBS="-L${with_alsa}/lib -lalsa" + ALSA_LIBS="-L${with_alsa}/lib -lasound" ALSA_CFLAGS="-I${with_alsa}/include" ALSA_FOUND=yes fi @@ -46788,7 +46788,7 @@ $as_echo "$as_me: WARNING: alsa not used, so --with-alsa is ignored" >&2;} ALSA_FOUND=yes fi if test "x${with_alsa_lib}" != x; then - ALSA_LIBS="-L${with_alsa_lib} -lalsa" + ALSA_LIBS="-L${with_alsa_lib} -lasound" ALSA_FOUND=yes fi if test "x$ALSA_FOUND" = xno; then diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index fa96a03fa88..dccec779cfc 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -562,7 +562,7 @@ AC_DEFUN_ONCE([LIB_SETUP_ALSA], fi if test "x${with_alsa}" != x; then - ALSA_LIBS="-L${with_alsa}/lib -lalsa" + ALSA_LIBS="-L${with_alsa}/lib -lasound" ALSA_CFLAGS="-I${with_alsa}/include" ALSA_FOUND=yes fi @@ -571,7 +571,7 @@ AC_DEFUN_ONCE([LIB_SETUP_ALSA], ALSA_FOUND=yes fi if test "x${with_alsa_lib}" != x; then - ALSA_LIBS="-L${with_alsa_lib} -lalsa" + ALSA_LIBS="-L${with_alsa_lib} -lasound" ALSA_FOUND=yes fi if test "x$ALSA_FOUND" = xno; then From b4e3a62871b11fae5bd6a40b664ea30f1d00cca4 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 10 Feb 2014 14:25:17 +0100 Subject: [PATCH 067/265] 8032632: Wrong version for the first jdk8 fcs build Reviewed-by: katleman --- common/autoconf/spec.gmk.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 3ba5d5a2d8d..dec8cd5ff8c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -172,7 +172,7 @@ RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX) COOKED_BUILD_NUMBER:=@COOKED_BUILD_NUMBER@ # These variables need to be generated here so that MILESTONE and # JDK_BUILD_NUMBER can be overridden on the make command line. -ifeq ($(MILESTONE),) +ifeq ($(MILESTONE), fcs) RELEASE=$(JDK_VERSION)$(BUILD_VARIANT_RELEASE) else RELEASE=$(JDK_VERSION)-$(MILESTONE)$(BUILD_VARIANT_RELEASE) From e7257d8d2a3938e194125bc34733d93188a9865a Mon Sep 17 00:00:00 2001 From: Iris Clark Date: Mon, 10 Feb 2014 12:53:40 -0800 Subject: [PATCH 068/265] 8034146: Update hgforest.sh for new closed tree Reviewed-by: jcoomes --- common/bin/hgforest.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index 2282c3239ca..d8164d60316 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then fi done if [ "${pull_extra_base}" != "" ] ; then - subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" + subrepos_extra="closed jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` pull_extra="${pull_extra_base}/${pull_default_tail}" for i in ${subrepos_extra} ; do From 7331f030bd621fe95a7da7c78a052575d0c417a5 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 11 Feb 2014 10:44:23 +0100 Subject: [PATCH 069/265] 8034098: Configure leaves 'a.out' in root dir Reviewed-by: tbell, ihse --- common/autoconf/generated-configure.sh | 4 ++-- common/autoconf/toolchain.m4 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 849e4746005..25db0b333ca 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4092,7 +4092,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1391775920 +DATE_WHEN_GENERATED=1392111785 ############################################################################### # @@ -42275,7 +42275,7 @@ $as_echo "no" >&6; } $as_echo "yes" >&6; } USING_BROKEN_SUSE_LD=yes fi - rm -rf version-script.map main.c + rm -rf version-script.map main.c a.out fi diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index f358daf3473..03e8a6b82aa 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -1205,7 +1205,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_MISC], AC_MSG_RESULT(yes) USING_BROKEN_SUSE_LD=yes fi - rm -rf version-script.map main.c + rm -rf version-script.map main.c a.out fi AC_SUBST(USING_BROKEN_SUSE_LD) ]) From d45fc51a447108eb3af72379d28be490bdd6ec1f Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 13 Feb 2014 00:00:20 +0100 Subject: [PATCH 070/265] 8034191: Move relevant parts of build system to new closed repo Reviewed-by: erikj, tbell --- common/autoconf/autogen.sh | 4 +-- common/autoconf/configure | 4 +-- common/autoconf/generated-configure.sh | 36 +++++++++++++------------- common/autoconf/jdk-options.m4 | 16 +++++------- common/autoconf/spec.gmk.in | 12 ++++++--- make/Main.gmk | 6 ++--- 6 files changed, 40 insertions(+), 38 deletions(-) diff --git a/common/autoconf/autogen.sh b/common/autoconf/autogen.sh index 69bb67ee426..162f27833cf 100644 --- a/common/autoconf/autogen.sh +++ b/common/autoconf/autogen.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ else fi if test "x$CUSTOM_CONFIG_DIR" = "x"; then - custom_script_dir="$script_dir/../../jdk/make/closed/autoconf" + custom_script_dir="$script_dir/../../closed/autoconf" else custom_script_dir=$CUSTOM_CONFIG_DIR fi diff --git a/common/autoconf/configure b/common/autoconf/configure index b73609a1de2..52515366bad 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ CONFIGURE_COMMAND_LINE="$@" conf_script_dir=`dirname $0` if [ "$CUSTOM_CONFIG_DIR" = "" ]; then - conf_custom_script_dir="$conf_script_dir/../../jdk/make/closed/autoconf" + conf_custom_script_dir="$conf_script_dir/../../closed/autoconf" else conf_custom_script_dir=$CUSTOM_CONFIG_DIR fi diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 25db0b333ca..4bbc05c7af9 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -968,7 +968,6 @@ BASH BASENAME DATE_WHEN_CONFIGURED CONFIGURE_COMMAND_LINE -CUSTOM_MAKE_DIR target_alias host_alias build_alias @@ -1010,12 +1009,12 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking -with_custom_make_dir with_target_bits with_sys_root with_tools_dir with_devkit enable_openjdk_only +with_custom_make_dir with_jdk_variant with_jvm_interpreter with_jvm_variants @@ -1833,7 +1832,6 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-custom-make-dir use this directory for custom build/make files --with-target-bits build 32-bit or 64-bit binaries (for platforms that support it), e.g. --with-target-bits=32 [guessed] --with-sys-root pass this sys-root to the compilers and tools (for @@ -1842,6 +1840,8 @@ Optional Packages: cross-compiling) --with-devkit use this directory as base for tools-dir and sys-root (for cross-compiling) + --with-custom-make-dir Deprecated. Option is kept for backwards + compatibility and is ignored --with-jdk-variant JDK variant to build (normal) [normal] --with-jvm-interpreter JVM interpreter to build (template, cpp) [template] --with-jvm-variants JVM variants (separated by commas) to build (server, @@ -1863,7 +1863,7 @@ Optional Packages: --with-update-version Set update version value for build [b00] --with-user-release-suffix Add a custom string to the version string if build - number isn't set.[username_builddateb00] + number is not set.[username_builddateb00] --with-build-number Set build number value for build [b00] --with-boot-jdk path to Boot JDK (used to bootstrap build) [probed] --with-boot-jdk-jvmargs specify JVM arguments to be passed to all @@ -3780,7 +3780,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -3831,18 +3831,6 @@ pkgadd_help() { -# Support for customization of the build process. Some build files -# will include counterparts from this location, if they exist. This allows -# for a degree of customization of the build targets and the rules/recipes -# to create them - -# Check whether --with-custom-make-dir was given. -if test "${with_custom_make_dir+set}" = set; then : - withval=$with_custom_make_dir; CUSTOM_MAKE_DIR=$with_custom_make_dir -fi - - - # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4092,7 +4080,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1392111785 +DATE_WHEN_GENERATED=1392245654 ############################################################################### # @@ -14307,6 +14295,18 @@ $as_echo "$as_me: WARNING: No closed source present, --enable-openjdk-only makes + # custom-make-dir is deprecated. Please use your custom-hook.m4 to override + # the IncludeCustomExtension macro. + + +# Check whether --with-custom-make-dir was given. +if test "${with_custom_make_dir+set}" = set; then : + withval=$with_custom_make_dir; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-custom-make-dir is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-custom-make-dir is deprecated and will be ignored." >&2;} +fi + + + # These are needed to be able to create a configuration name (and thus the output directory) diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 44563af163f..f024b7aca82 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -332,6 +332,10 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_OPEN_OR_CUSTOM], fi AC_SUBST(SET_OPENJDK) + + # custom-make-dir is deprecated. Please use your custom-hook.m4 to override + # the IncludeCustomExtension macro. + BASIC_DEPRECATED_ARG_WITH(custom-make-dir) ]) AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], @@ -482,7 +486,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_VERSION_NUMBERS], fi AC_ARG_WITH(user-release-suffix, [AS_HELP_STRING([--with-user-release-suffix], - [Add a custom string to the version string if build number isn't set.@<:@username_builddateb00@:>@])]) + [Add a custom string to the version string if build number is not set.@<:@username_builddateb00@:>@])]) if test "x$with_user_release_suffix" = xyes; then AC_MSG_ERROR([Release suffix must have a value]) elif test "x$with_user_release_suffix" != x; then @@ -605,11 +609,3 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], AC_SUBST(CFLAGS_DEBUG_SYMBOLS) AC_SUBST(CXXFLAGS_DEBUG_SYMBOLS) ]) - -# Support for customization of the build process. Some build files -# will include counterparts from this location, if they exist. This allows -# for a degree of customization of the build targets and the rules/recipes -# to create them -AC_ARG_WITH([custom-make-dir], [AS_HELP_STRING([--with-custom-make-dir], -[use this directory for custom build/make files])], [CUSTOM_MAKE_DIR=$with_custom_make_dir]) -AC_SUBST(CUSTOM_MAKE_DIR) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index dec8cd5ff8c..9d7859dfad3 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -147,9 +147,6 @@ HOTSPOT_TOPDIR:=@HOTSPOT_TOPDIR@ NASHORN_TOPDIR:=@NASHORN_TOPDIR@ COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@ -# Location where build customization files may be found -CUSTOM_MAKE_DIR:=@CUSTOM_MAKE_DIR@ - # Information gathered from the version.numbers file. JDK_MAJOR_VERSION:=@JDK_MAJOR_VERSION@ JDK_MINOR_VERSION:=@JDK_MINOR_VERSION@ @@ -677,5 +674,14 @@ JRE_BUNDLE_SUBDIR=j2re-bundle/jre$(JDK_VERSION).jre/Contents JDK_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JDK_BUNDLE_SUBDIR) JRE_BUNDLE_DIR=$(IMAGES_OUTPUTDIR)/$(JRE_BUNDLE_SUBDIR) +# This macro is called to allow inclusion of closed source counterparts. +# Unless overridden in closed sources, it expands to nothing. +# Usage: This function is called in an open makefile, with the following +# arguments: +# $1 the name of the repo, or empty if the top-level repo. +# $2 the name of the makefile +define IncludeCustomExtension +endef + # Include the custom-spec.gmk file if it exists -include $(dir @SPEC@)/custom-spec.gmk diff --git a/make/Main.gmk b/make/Main.gmk index acb4faa4405..02e4507a388 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,8 @@ include $(SPEC) # Load the vital tools for all the makefiles. include $(SRC_ROOT)/make/common/MakeBase.gmk -# Include the corresponding custom file, if present. --include $(CUSTOM_MAKE_DIR)/Main.gmk +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, , Main.gmk)) ### Clean up from previous run From c59b650c964175441a8368d4c405a4fd97e83d4a Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Wed, 12 Feb 2014 17:03:39 -0800 Subject: [PATCH 071/265] 8030350: Enable additional compiler warnings for GCC Reviewed-by: dholmes, coleenp, tbell, erikj, ihse --- common/autoconf/generated-configure.sh | 5 +++-- common/autoconf/toolchain.m4 | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 4bbc05c7af9..8215b391c2f 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4080,7 +4080,7 @@ pkgadd_help() { #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1392245654 +DATE_WHEN_GENERATED=1392253412 ############################################################################### # @@ -41874,7 +41874,8 @@ fi # case $COMPILER_NAME in gcc ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -W -Wall -Wno-unused -Wno-parentheses \ + # these options are used for both C and C++ compiles + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe \ -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" case $OPENJDK_TARGET_CPU_ARCH in diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 03e8a6b82aa..5e7717de024 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -898,7 +898,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_FOR_JDK], # case $COMPILER_NAME in gcc ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -W -Wall -Wno-unused -Wno-parentheses \ + # these options are used for both C and C++ compiles + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe \ -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" case $OPENJDK_TARGET_CPU_ARCH in From 8f9dfe90ede853b925e8c1060eddaa1866fdb8e8 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 13 Feb 2014 23:30:08 +0100 Subject: [PATCH 072/265] 8034199: Add 'reconfigure' target for re-creating a configuration Reviewed-by: erikj, tbell --- common/autoconf/basics.m4 | 3 -- common/autoconf/configure | 61 ++++++++++++++++++++++---- common/autoconf/generated-configure.sh | 5 +-- common/autoconf/spec.gmk.in | 3 ++ make/Main.gmk | 13 +++++- 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index d34615d5a2a..cc17ae0041e 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -558,9 +558,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], # You can run make from the OUTPUT_ROOT, or from the top-level Makefile # which will look for generated configurations AC_CONFIG_FILES([$OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in]) - - # Save the arguments given to us - echo "$CONFIGURE_COMMAND_LINE" > $OUTPUT_ROOT/configure-arguments ]) AC_DEFUN_ONCE([BASIC_SETUP_LOGGING], diff --git a/common/autoconf/configure b/common/autoconf/configure index 52515366bad..2c9cd7293b9 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -28,7 +28,6 @@ if test "x$BASH_VERSION" = x; then exit 1 fi -CONFIGURE_COMMAND_LINE="$@" conf_script_dir=`dirname $0` if [ "$CUSTOM_CONFIG_DIR" = "" ]; then @@ -110,14 +109,40 @@ fi if test "x$conf_debug_configure" = xtrue; then conf_debug_configure=recursive fi + ### ### Process command-line arguments ### + +# Returns a shell-escaped version of the argument given. +function shell_quote() { + if [[ -n "$1" ]]; then + # Uses only shell-safe characters? No quoting needed. + # '=' is a zsh meta-character, but only in word-initial position. + if [[ "$1" =~ ^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.:,%/+=_-]+$ && ! "$1" =~ ^= ]]; then + quoted="$1" + else + if [[ "$1" =~ [\'!] ]]; then + # csh does history expansion within single quotes, but not + # when backslash-escaped! + local quoted_quote="'\\''" quoted_exclam="'\\!'" + word="${1//\'/${quoted_quote}}" + word="${1//\!/${quoted_exclam}}" + fi + quoted="'$1'" + fi + echo "$quoted" + fi +} + conf_processed_arguments=() +conf_quoted_arguments=() conf_openjdk_target= for conf_option do + + # Process (and remove) our own extensions that will not be passed to autoconf case $conf_option in --openjdk-target=*) conf_openjdk_target=`expr "X$conf_option" : '[^=]*=\(.*\)'` @@ -128,18 +153,35 @@ do export conf_debug_configure fi ;; - [^-]*=*) - # Add name of variable to CONFIGURE_OVERRIDDEN_VARIABLES list inside !...!. - conf_env_var=`expr "x$conf_option" : 'x\([^=]*\)='` - CONFIGURE_OVERRIDDEN_VARIABLES="$CONFIGURE_OVERRIDDEN_VARIABLES!$conf_env_var!" - # ... and then process argument as usual - conf_processed_arguments=("${conf_processed_arguments[@]}" "$conf_option") - ;; *) conf_processed_arguments=("${conf_processed_arguments[@]}" "$conf_option") ;; esac + # Store all variables overridden on the command line + case $conf_option in + [^-]*=*) + # Add name of variable to CONFIGURE_OVERRIDDEN_VARIABLES list inside !...!. + conf_env_var=`expr "x$conf_option" : 'x\([^=]*\)='` + CONFIGURE_OVERRIDDEN_VARIABLES="$CONFIGURE_OVERRIDDEN_VARIABLES!$conf_env_var!" + ;; + esac + + # Save the arguments, intelligently quoted for CONFIGURE_COMMAND_LINE. + case $conf_option in + *=*) + conf_option_name=`expr "x$conf_option" : 'x\([^=]*\)='` + conf_option_name=$(shell_quote "$conf_option_name") + conf_option_value=`expr "x$conf_option" : 'x[^=]*=\(.*\)'` + conf_option_value=$(shell_quote "$conf_option_value") + conf_quoted_arguments=("${conf_quoted_arguments[@]}" "$conf_option_name=$conf_option_value") + ;; + *) + conf_quoted_arguments=("${conf_quoted_arguments[@]}" "$(shell_quote "$conf_option")") + ;; + esac + + # Check for certain autoconf options that require extra action case $conf_option in -build | --build | --buil | --bui | --bu |-build=* | --build=* | --buil=* | --bui=* | --bu=*) conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;; @@ -152,6 +194,9 @@ do esac done +# Save the quoted command line +CONFIGURE_COMMAND_LINE="${conf_quoted_arguments[@]}" + if test "x$conf_legacy_crosscompile" != "x"; then if test "x$conf_openjdk_target" != "x"; then echo "Error: Specifying --openjdk-target together with autoconf" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 8215b391c2f..f6c6c3dfb0f 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4080,7 +4080,7 @@ pkgadd_help() { #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1392253412 +DATE_WHEN_GENERATED=1392330495 ############################################################################### # @@ -14825,9 +14825,6 @@ $as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is inval ac_config_files="$ac_config_files $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in" - # Save the arguments given to us - echo "$CONFIGURE_COMMAND_LINE" > $OUTPUT_ROOT/configure-arguments - # Must be done before we can call HELP_MSG_MISSING_DEPENDENCY. diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 9d7859dfad3..5a2f868b823 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -48,6 +48,9 @@ define NEWLINE endef +# The command line given to configure. +CONFIGURE_COMMAND_LINE:=@CONFIGURE_COMMAND_LINE@ + # A self-referential reference to this file. SPEC:=@SPEC@ diff --git a/make/Main.gmk b/make/Main.gmk index 02e4507a388..b13903aa23d 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -71,8 +71,9 @@ all: images docs # Setup a rule for SPEC file that fails if executed. This check makes sure the configuration # is up to date after changes to configure $(SPEC): $(wildcard $(SRC_ROOT)/common/autoconf/*) - @$(ECHO) ERROR: $(SPEC) is not up to date - @$(ECHO) Please rerun configure! + @$(ECHO) "ERROR: $(SPEC) is not up to date." + @$(ECHO) "Please rerun configure! Easiest way to do this is by running" + @$(ECHO) "'make reconfigure'." @if test "x$(IGNORE_OLD_CONFIG)" != "xtrue"; then exit 1; fi start-make: $(SPEC) @@ -235,6 +236,14 @@ clean-docs: $(call CleanComponent,docstemp) clean-test: $(call CleanComponent,testoutput) + +reconfigure: + ifneq ($(CONFIGURE_COMMAND_LINE), ) + @$(ECHO) "Re-running configure using arguments '$(CONFIGURE_COMMAND_LINE)'" + else + @$(ECHO) "Re-running configure using default settings" + endif + @( cd $(OUTPUT_ROOT) && $(BASH) $(TOPDIR)/configure "$(CONFIGURE_COMMAND_LINE)" ) .PHONY: langtools corba jaxp jaxws hotspot jdk nashorn images overlay-images install test docs .PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only nashorn-only images-only overlay-images-only install-only test-only docs-only From 5ec82f84c33fe7ac9db2256a9bcd988221fd1eea Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Mon, 17 Feb 2014 10:48:48 -0800 Subject: [PATCH 073/265] 8034979: Configuration help messages don't consider --no-create Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 25 +++++++++++++++++++++---- common/autoconf/help.m4 | 23 ++++++++++++++++++++--- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index f6c6c3dfb0f..741bf99f490 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4080,7 +4080,7 @@ pkgadd_help() { #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1392330495 +DATE_WHEN_GENERATED=1392662653 ############################################################################### # @@ -49908,8 +49908,19 @@ $CHMOD +x $OUTPUT_ROOT/compare.sh printf "\n" printf "====================================================\n" - printf "A new configuration has been successfully created in\n" - printf "$OUTPUT_ROOT\n" + if test "x$no_create" != "xyes"; then + if test "x$IS_RECONFIGURE" != "xyes"; then + printf "A new configuration has been successfully created in\n %s\n" "$OUTPUT_ROOT" + else + printf "The existing configuration has been successfully updated in\n %s\n" "$OUTPUT_ROOT" + fi + else + if test "x$IS_RECONFIGURE" != "xyes"; then + printf "A configuration has been successfully checked but not created\n" + else + printf "The existing configuration has been successfully checked in\n %s\n" "$OUTPUT_ROOT" + fi + fi if test "x$CONFIGURE_COMMAND_LINE" != x; then printf "using configure arguments '$CONFIGURE_COMMAND_LINE'.\n" else @@ -49963,10 +49974,16 @@ $CHMOD +x $OUTPUT_ROOT/compare.sh printf "\n" fi - if test "x$IS_RECONFIGURE" = "xyes"; then + if test "x$IS_RECONFIGURE" = "xyes" && test "x$no_create" != "xyes"; then printf "WARNING: The result of this configuration has overridden an older\n" printf "configuration. You *should* run 'make clean' to make sure you get a\n" printf "proper build. Failure to do so might result in strange build problems.\n" printf "\n" fi + if test "x$IS_RECONFIGURE" != "xyes" && test "x$no_create" = "xyes"; then + printf "WARNING: The result of this configuration was not saved.\n" + printf "You should run without '--no-create | -n' to create the configuration.\n" + printf "\n" + fi + diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index 89ecfbef68c..b24779cf94d 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -157,8 +157,19 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "\n" printf "====================================================\n" - printf "A new configuration has been successfully created in\n" - printf "$OUTPUT_ROOT\n" + if test "x$no_create" != "xyes"; then + if test "x$IS_RECONFIGURE" != "xyes"; then + printf "A new configuration has been successfully created in\n %s\n" "$OUTPUT_ROOT" + else + printf "The existing configuration has been successfully updated in\n %s\n" "$OUTPUT_ROOT" + fi + else + if test "x$IS_RECONFIGURE" != "xyes"; then + printf "A configuration has been successfully checked but not created\n" + else + printf "The existing configuration has been successfully checked in\n %s\n" "$OUTPUT_ROOT" + fi + fi if test "x$CONFIGURE_COMMAND_LINE" != x; then printf "using configure arguments '$CONFIGURE_COMMAND_LINE'.\n" else @@ -212,10 +223,16 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "\n" fi - if test "x$IS_RECONFIGURE" = "xyes"; then + if test "x$IS_RECONFIGURE" = "xyes" && test "x$no_create" != "xyes"; then printf "WARNING: The result of this configuration has overridden an older\n" printf "configuration. You *should* run 'make clean' to make sure you get a\n" printf "proper build. Failure to do so might result in strange build problems.\n" printf "\n" fi + + if test "x$IS_RECONFIGURE" != "xyes" && test "x$no_create" = "xyes"; then + printf "WARNING: The result of this configuration was not saved.\n" + printf "You should run without '--no-create | -n' to create the configuration.\n" + printf "\n" + fi ]) From 3f3b3c2a86a15cbd71e0c367606310ff520e9454 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:41:04 -0800 Subject: [PATCH 074/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- THIRD_PARTY_README | 1706 ++++++++++++++++++++------------------------ 1 file changed, 766 insertions(+), 940 deletions(-) diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README index 759733bfceb..ba48858c28f 100644 --- a/THIRD_PARTY_README +++ b/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- @@ -3383,397 +3603,3 @@ included with JRE 7, JDK 7, and OpenJDK 7, except where noted: ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Network Security -Services (NSS), which is supplied with the JDK test suite in the OpenJDK -source code repository. It is licensed under Mozilla Public License (MPL), -version 2.0. - -The NSS libraries are supplied in executable form, built from unmodified -NSS source code labeled with the "NSS_3.13.1_RTM" release tag. - -The NSS source code is available in the OpenJDK source code repository at: - jdk/test/sun/security/pkcs11/nss/src - -The NSS libraries are available in the OpenJDK source code repository at: - jdk/test/sun/security/pkcs11/nss/lib - ---- begin of LICENSE --- - -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - From cf5325349ea80fae67f85dc4d3d9fe1cb647d4df Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:42:14 -0800 Subject: [PATCH 075/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- corba/THIRD_PARTY_README | 1312 ++++++++++++++++++++++---------------- 1 file changed, 766 insertions(+), 546 deletions(-) diff --git a/corba/THIRD_PARTY_README b/corba/THIRD_PARTY_README index ee5463a922e..ba48858c28f 100644 --- a/corba/THIRD_PARTY_README +++ b/corba/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- From 2e916722f5fc3954241318bf032cac5fdad44870 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:42:26 -0800 Subject: [PATCH 076/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- hotspot/THIRD_PARTY_README | 1312 +++++++++++++++++++++--------------- 1 file changed, 766 insertions(+), 546 deletions(-) diff --git a/hotspot/THIRD_PARTY_README b/hotspot/THIRD_PARTY_README index ee5463a922e..ba48858c28f 100644 --- a/hotspot/THIRD_PARTY_README +++ b/hotspot/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- From 176884b8190dcf1301e60611fe108e3b37a8cc76 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Tue, 18 Feb 2014 10:51:16 -0800 Subject: [PATCH 077/265] 8033980: Xerces Update: datatype XMLGregorianCalendarImpl and DurationImpl Reviewed-by: dfuchs, lancea, alanb --- .../internal/jaxp/datatype/DurationImpl.java | 212 ++++---- .../datatype/XMLGregorianCalendarImpl.java | 473 ++++++++++-------- 2 files changed, 367 insertions(+), 318 deletions(-) diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java index 4e4f7d47248..da5de3e1ff5 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -106,24 +107,20 @@ class DurationImpl extends Duration implements Serializable { - /** - *

Number of Fields.

- */ - private static final int FIELD_NUM = 6; /** *

Internal array of value Fields.

*/ - private static final DatatypeConstants.Field[] FIELDS = new DatatypeConstants.Field[]{ - DatatypeConstants.YEARS, - DatatypeConstants.MONTHS, - DatatypeConstants.DAYS, - DatatypeConstants.HOURS, - DatatypeConstants.MINUTES, - DatatypeConstants.SECONDS - }; + private static final DatatypeConstants.Field[] FIELDS = new DatatypeConstants.Field[]{ + DatatypeConstants.YEARS, + DatatypeConstants.MONTHS, + DatatypeConstants.DAYS, + DatatypeConstants.HOURS, + DatatypeConstants.MINUTES, + DatatypeConstants.SECONDS + }; - /** + /** *

Internal array of value Field ids.

*/ private static final int[] FIELD_IDS = { @@ -141,9 +138,9 @@ class DurationImpl private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); /** - *

BigDecimal value of 0.

- */ - private static final BigDecimal ZERO = BigDecimal.valueOf((long) 0); + *

BigDecimal value of 0.

+ */ + private static final BigDecimal ZERO = BigDecimal.valueOf(0); /** *

Indicates the sign. -1, 0 or 1 if the duration is negative, @@ -186,17 +183,17 @@ class DurationImpl */ protected BigDecimal seconds; - /** - * Returns the sign of this duration in -1,0, or 1. - * - * @return - * -1 if this duration is negative, 0 if the duration is zero, - * and 1 if the duration is postive. - */ - public int getSign() { + /** + * Returns the sign of this duration in -1,0, or 1. + * + * @return + * -1 if this duration is negative, 0 if the duration is zero, + * and 1 if the duration is postive. + */ + public int getSign() { - return signum; - } + return signum; + } /** * TODO: Javadoc @@ -206,20 +203,20 @@ class DurationImpl */ protected int calcSignum(boolean isPositive) { if ((years == null || years.signum() == 0) - && (months == null || months.signum() == 0) - && (days == null || days.signum() == 0) - && (hours == null || hours.signum() == 0) - && (minutes == null || minutes.signum() == 0) - && (seconds == null || seconds.signum() == 0)) { + && (months == null || months.signum() == 0) + && (days == null || days.signum() == 0) + && (hours == null || hours.signum() == 0) + && (minutes == null || minutes.signum() == 0) + && (seconds == null || seconds.signum() == 0)) { return 0; - } - - if (isPositive) { - return 1; - } else { - return -1; - } + } + if (isPositive) { + return 1; + } + else { + return -1; + } } /** @@ -357,7 +354,7 @@ class DurationImpl } // int -> BigInteger - return new BigInteger(String.valueOf(i)); + return BigInteger.valueOf(i); } /** @@ -373,14 +370,16 @@ class DurationImpl if (l > 0) { signum = 1; - } else if (l < 0) { + } + else if (l < 0) { signum = -1; if (l == 0x8000000000000000L) { // negating 0x8000000000000000L causes an overflow l++; } l *= -1; - } else { + } + else { signum = 0; } @@ -454,21 +453,22 @@ class DurationImpl throws IllegalArgumentException { // only if I could use the JDK1.4 regular expression .... + if (lexicalRepresentation == null) { + throw new NullPointerException(); + } + final String s = lexicalRepresentation; boolean positive; int[] idx = new int[1]; int length = s.length(); boolean timeRequired = false; - if (lexicalRepresentation == null) { - throw new NullPointerException(); - } - idx[0] = 0; if (length != idx[0] && s.charAt(idx[0]) == '-') { idx[0]++; positive = false; - } else { + } + else { positive = true; } @@ -484,8 +484,8 @@ class DurationImpl String[] dateParts = new String[3]; int[] datePartsIndex = new int[3]; while (length != idx[0] - && isDigit(s.charAt(idx[0])) - && dateLen < 3) { + && isDigit(s.charAt(idx[0])) + && dateLen < 3) { datePartsIndex[dateLen] = idx[0]; dateParts[dateLen++] = parsePiece(s, idx); } @@ -493,7 +493,8 @@ class DurationImpl if (length != idx[0]) { if (s.charAt(idx[0]++) == 'T') { timeRequired = true; - } else { + } + else { throw new IllegalArgumentException(s); // ,idx[0]-1); } } @@ -502,8 +503,8 @@ class DurationImpl String[] timeParts = new String[3]; int[] timePartsIndex = new int[3]; while (length != idx[0] - && isDigitOrPeriod(s.charAt(idx[0])) - && timeLen < 3) { + && isDigitOrPeriod(s.charAt(idx[0])) + && timeLen < 3) { timePartsIndex[timeLen] = idx[0]; timeParts[timeLen++] = parsePiece(s, idx); } @@ -604,6 +605,9 @@ class DurationImpl int idx = tokens.length(); for (int i = len - 1; i >= 0; i--) { + if (parts[i] == null) { + throw new IllegalArgumentException(whole); + } int nidx = tokens.lastIndexOf( parts[i].charAt(parts[i].length() - 1), @@ -722,8 +726,7 @@ class DurationImpl */ public int compare(Duration rhs) { - BigInteger maxintAsBigInteger = BigInteger.valueOf((long) Integer.MAX_VALUE); - BigInteger minintAsBigInteger = BigInteger.valueOf((long) Integer.MIN_VALUE); + BigInteger maxintAsBigInteger = BigInteger.valueOf(Integer.MAX_VALUE); // check for fields that are too large in this Duration if (years != null && years.compareTo(maxintAsBigInteger) == 1) { @@ -778,7 +781,7 @@ class DurationImpl if (seconds != null && seconds.toBigInteger().compareTo(maxintAsBigInteger) == 1) { throw new UnsupportedOperationException( DatatypeMessageFormatter.formatMessage(null, "TooLarge", - new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.SECONDS.toString(), seconds.toString()}) + new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.SECONDS.toString(), toString(seconds)}) //this.getClass().getName() + "#compare(Duration duration)" //+ " seconds too large to be supported by this implementation " @@ -957,9 +960,9 @@ class DurationImpl return resultA; } - private int compareResults(int resultA, int resultB){ + private int compareResults(int resultA, int resultB) { - if ( resultB == DatatypeConstants.INDETERMINATE ) { + if ( resultB == DatatypeConstants.INDETERMINATE ) { return DatatypeConstants.INDETERMINATE; } else if ( resultA!=resultB) { @@ -1007,25 +1010,25 @@ class DurationImpl buf.append('P'); if (years != null) { - buf.append(years + "Y"); + buf.append(years).append('Y'); } if (months != null) { - buf.append(months + "M"); + buf.append(months).append('M'); } if (days != null) { - buf.append(days + "D"); + buf.append(days).append('D'); } if (hours != null || minutes != null || seconds != null) { buf.append('T'); if (hours != null) { - buf.append(hours + "H"); + buf.append(hours).append('H'); } if (minutes != null) { - buf.append(minutes + "M"); + buf.append(minutes).append('M'); } if (seconds != null) { - buf.append(toString(seconds) + "S"); + buf.append(toString(seconds)).append('S'); } } @@ -1055,10 +1058,12 @@ class DurationImpl int insertionPoint = intString.length() - scale; if (insertionPoint == 0) { /* Point goes right before intVal */ return "0." + intString; - } else if (insertionPoint > 0) { /* Point goes inside intVal */ + } + else if (insertionPoint > 0) { /* Point goes inside intVal */ buf = new StringBuffer(intString); buf.insert(insertionPoint, '.'); - } else { /* We must insert zeros between point and intVal */ + } + else { /* We must insert zeros between point and intVal */ buf = new StringBuffer(3 - insertionPoint + intString.length()); buf.append("0."); for (int i = 0; i < -insertionPoint; i++) { @@ -1302,7 +1307,8 @@ class DurationImpl Number n = getField(field); if (n == null) { return 0; - } else { + } + else { return n.intValue(); } } @@ -1340,8 +1346,7 @@ class DurationImpl public long getTimeInMillis(final Calendar startInstant) { Calendar cal = (Calendar) startInstant.clone(); addTo(cal); - return getCalendarTimeInMillis(cal) - - getCalendarTimeInMillis(startInstant); + return getCalendarTimeInMillis(cal) - getCalendarTimeInMillis(startInstant); } /** @@ -1451,13 +1456,13 @@ class DurationImpl int days = (int) (diff / (1000L * 60L * 60L * 24L)); return new DurationImpl( - days >= 0, - null, - null, - wrap(Math.abs(days)), - (BigInteger) getField(DatatypeConstants.HOURS), - (BigInteger) getField(DatatypeConstants.MINUTES), - (BigDecimal) getField(DatatypeConstants.SECONDS)); + days >= 0, + null, + null, + wrap(Math.abs(days)), + (BigInteger) getField(DatatypeConstants.HOURS), + (BigInteger) getField(DatatypeConstants.MINUTES), + (BigDecimal) getField(DatatypeConstants.SECONDS)); } /** @@ -1547,14 +1552,16 @@ class DurationImpl } else { carry = ZERO; } - } else { + } + else { carry = bd.multiply(FACTORS[i]); } } if (seconds != null) { buf[5] = seconds.multiply(factor).add(carry); - } else { + } + else { buf[5] = carry; } @@ -1581,14 +1588,17 @@ class DurationImpl if (f == DatatypeConstants.SECONDS) { if (seconds != null) { return seconds; - } else { + } + else { return ZERO; } - } else { + } + else { BigInteger bi = (BigInteger) getField(f); if (bi == null) { return ZERO; - } else { + } + else { return new BigDecimal(bi); } } @@ -1607,7 +1617,8 @@ class DurationImpl boolean canBeNull) { if (canBeNull && value.signum() == 0) { return null; - } else { + } + else { return value.unscaledValue(); } } @@ -1616,7 +1627,7 @@ class DurationImpl * 1 unit of FIELDS[i] is equivalent to FACTORS[i] unit of * FIELDS[i+1]. */ - private static final BigDecimal[] FACTORS = new BigDecimal[]{ + private static final BigDecimal[] FACTORS = new BigDecimal[] { BigDecimal.valueOf(12), null/*undefined*/, BigDecimal.valueOf(24), @@ -1963,11 +1974,21 @@ class DurationImpl date.setTime(getCalendarTimeInMillis(cal)); } + /** + * Returns time value in milliseconds + * @param cal A calendar object + * @return time value + * + * Diff from Xerces; Use JDK 1.5 feature. + */ + private static long getCalendarTimeInMillis(Calendar cal) { + return cal.getTimeInMillis(); + } + /** *

Stream Unique Identifier.

* - *

TODO: Serialization should use the XML string representation as - * the serialization format to ensure future compatibility.

+ *

Serialization uses the lexical form returned by toString().

*/ private static final long serialVersionUID = 1L; @@ -1996,25 +2017,10 @@ class DurationImpl } private Object readResolve() throws ObjectStreamException { - // try { return new DurationImpl(lexical); - // } catch( ParseException e ) { - // throw new StreamCorruptedException("unable to parse "+lexical+" as duration"); - // } } private static final long serialVersionUID = 1L; } - /** - * Calls the {@link Calendar#getTimeInMillis} method. - * Prior to JDK1.4, this method was protected and therefore - * cannot be invoked directly. - * - * In future, this should be replaced by - * cal.getTimeInMillis() - */ - private static long getCalendarTimeInMillis(Calendar cal) { - return cal.getTime().getTime(); - } } diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java index dac7fbf09f2..6c629e95184 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/datatype/XMLGregorianCalendarImpl.java @@ -25,6 +25,8 @@ package com.sun.org.apache.xerces.internal.jaxp.datatype; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; @@ -195,6 +197,17 @@ public class XMLGregorianCalendarImpl extends XMLGregorianCalendar implements Serializable, Cloneable { + /** Backup values **/ + transient private BigInteger orig_eon; + transient private int orig_year = DatatypeConstants.FIELD_UNDEFINED; + transient private int orig_month = DatatypeConstants.FIELD_UNDEFINED; + transient private int orig_day = DatatypeConstants.FIELD_UNDEFINED; + transient private int orig_hour = DatatypeConstants.FIELD_UNDEFINED; + transient private int orig_minute = DatatypeConstants.FIELD_UNDEFINED; + transient private int orig_second = DatatypeConstants.FIELD_UNDEFINED; + transient private BigDecimal orig_fracSeconds; + transient private int orig_timezone = DatatypeConstants.FIELD_UNDEFINED; + /** *

Eon of this XMLGregorianCalendar.

*/ @@ -241,9 +254,14 @@ public class XMLGregorianCalendarImpl private BigDecimal fractionalSecond = null; /** - *

Constant to represent a billion.

+ *

BigInteger constant; representing a billion.

*/ - private static final BigInteger BILLION = new BigInteger("1000000000"); + private static final BigInteger BILLION_B = new BigInteger("1000000000"); + + /** + *

int constant; representing a billion.

+ */ + private static final int BILLION_I = 1000000000; /** *

Obtain a pure Gregorian Calendar by calling @@ -441,6 +459,23 @@ public class XMLGregorianCalendarImpl //"\"" + lexicalRepresentation + "\" is not a valid representation of an XML Gregorian Calendar value." ); } + + save(); + } + + /** + * save original values + */ + private void save() { + orig_eon = eon; + orig_year = year; + orig_month = month; + orig_day = day; + orig_hour = hour; + orig_minute = minute; + orig_second = second; + orig_fracSeconds = fractionalSecond; + orig_timezone = timezone; } /** @@ -479,14 +514,14 @@ public class XMLGregorianCalendarImpl BigDecimal fractionalSecond, int timezone) { - setYear(year); + setYear(year); setMonth(month); setDay(day); setTime(hour, minute, second, fractionalSecond); - setTimezone(timezone); + setTimezone(timezone); - // check for validity - if (!isValid()) { + // check for validity + if (!isValid()) { throw new IllegalArgumentException( DatatypeMessageFormatter.formatMessage(null, @@ -519,8 +554,9 @@ public class XMLGregorianCalendarImpl ); */ - } + } + save(); } /** @@ -547,17 +583,21 @@ public class XMLGregorianCalendarImpl int hour, int minute, int second, - int millisecond, + int millisecond, int timezone) { - setYear(year); + setYear(year); setMonth(month); setDay(day); setTime(hour, minute, second); - setTimezone(timezone); - setMillisecond(millisecond); + setTimezone(timezone); + BigDecimal realMilliseconds = null; + if (millisecond != DatatypeConstants.FIELD_UNDEFINED) { + realMilliseconds = BigDecimal.valueOf(millisecond, 3); + } + setFractionalSecond(realMilliseconds); - if (!isValid()) { + if (!isValid()) { throw new IllegalArgumentException( DatatypeMessageFormatter.formatMessage(null, @@ -580,7 +620,9 @@ public class XMLGregorianCalendarImpl ); */ - } + } + + save(); } /** @@ -661,6 +703,7 @@ public class XMLGregorianCalendarImpl // Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds. int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000); this.setTimezone(offsetInMinutes); + save(); } // Factories @@ -1164,7 +1207,7 @@ public class XMLGregorianCalendarImpl this.eon = null; this.year = DatatypeConstants.FIELD_UNDEFINED; } else { - BigInteger temp = year.remainder(BILLION); + BigInteger temp = year.remainder(BILLION_B); this.year = temp.intValue(); setEon(year.subtract(temp)); } @@ -1187,12 +1230,13 @@ public class XMLGregorianCalendarImpl if (year == DatatypeConstants.FIELD_UNDEFINED) { this.year = DatatypeConstants.FIELD_UNDEFINED; this.eon = null; - } else if (Math.abs(year) < BILLION.intValue()) { + } + else if (Math.abs(year) < BILLION_I) { this.year = year; this.eon = null; } else { BigInteger theYear = BigInteger.valueOf((long) year); - BigInteger remainder = theYear.remainder(BILLION); + BigInteger remainder = theYear.remainder(BILLION_B); this.year = remainder.intValue(); setEon(theYear.subtract(remainder)); } @@ -1688,6 +1732,9 @@ public class XMLGregorianCalendarImpl if (obj == null || !(obj instanceof XMLGregorianCalendar)) { return false; } + if (obj == this) { + return true; + } return compare((XMLGregorianCalendar) obj) == DatatypeConstants.EQUAL; } @@ -1950,51 +1997,36 @@ public class XMLGregorianCalendarImpl // no need to check for anything except for constraints // between fields. - //check if days in month is valid. Can be dependent on leap year. - if (getMonth() == DatatypeConstants.FEBRUARY) { - // years could not be set - int maxDays = 29; - - if (eon == null) { - if(year!=DatatypeConstants.FIELD_UNDEFINED) - maxDays = maximumDayInMonthFor(year,getMonth()); - } else { - BigInteger years = getEonAndYear(); - if (years != null) { - maxDays = maximumDayInMonthFor(getEonAndYear(), DatatypeConstants.FEBRUARY); + // check if days in month is valid. Can be dependent on leap year. + if (month != DatatypeConstants.FIELD_UNDEFINED && day != DatatypeConstants.FIELD_UNDEFINED) { + if (year != DatatypeConstants.FIELD_UNDEFINED) { + if (eon == null) { + if (day > maximumDayInMonthFor(year, month)) { + return false; + } + } + else if (day > maximumDayInMonthFor(getEonAndYear(), month)) { + return false; } } - if (getDay() > maxDays) { + // Use 2000 as a default since it's a leap year. + else if (day > maximumDayInMonthFor(2000, month)) { return false; } } // http://www.w3.org/2001/05/xmlschema-errata#e2-45 - if (getHour() == 24) { - if(getMinute() != 0) { - return false; - } else if (getSecond() != 0) { - return false; - } + if (hour == 24 && (minute != 0 || second != 0 || + (fractionalSecond != null && fractionalSecond.compareTo(DECIMAL_ZERO) != 0))) { + return false; } // XML Schema 1.0 specification defines year value of zero as // invalid. Allow this class to set year field to zero // since XML Schema 1.0 errata states that lexical zero will // be allowed in next version and treated as 1 B.C.E. - if (eon == null) { - // optimize check. - if (year == 0) { - return false; - } - } else { - BigInteger yearField = getEonAndYear(); - if (yearField != null) { - int result = compareField(yearField, BigInteger.ZERO); - if (result == DatatypeConstants.EQUAL) { - return false; - } - } + if (eon == null && year == 0) { + return false; } return true; } @@ -2213,7 +2245,7 @@ public class XMLGregorianCalendarImpl int quotient; if (endMonth < 0) { endMonth = (13 - 1) + endMonth + 1; - quotient = new BigDecimal(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue(); + quotient = BigDecimal.valueOf(intTemp - 1).divide(new BigDecimal(TWELVE), BigDecimal.ROUND_UP).intValue(); } else { quotient = (intTemp - 1) / (13 - 1); endMonth += 1; @@ -2259,18 +2291,20 @@ public class XMLGregorianCalendarImpl private static final BigInteger SIXTY = BigInteger.valueOf(60); private static final BigInteger TWENTY_FOUR = BigInteger.valueOf(24); private static final BigInteger TWELVE = BigInteger.valueOf(12); - private static final BigDecimal DECIMAL_ZERO = new BigDecimal("0"); - private static final BigDecimal DECIMAL_ONE = new BigDecimal("1"); - private static final BigDecimal DECIMAL_SIXTY = new BigDecimal("60"); + private static final BigDecimal DECIMAL_ZERO = BigDecimal.valueOf(0); + private static final BigDecimal DECIMAL_ONE = BigDecimal.valueOf(1); + private static final BigDecimal DECIMAL_SIXTY = BigDecimal.valueOf(60); - private static int daysInMonth[] = { 0, // XML Schema months start at 1. - 31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; + private static class DaysInMonth { + private static final int [] table = { 0, // XML Schema months start at 1. + 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + } private static int maximumDayInMonthFor(BigInteger year, int month) { if (month != DatatypeConstants.FEBRUARY) { - return daysInMonth[month]; + return DaysInMonth.table[month]; } else { if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) || (!year.mod(HUNDRED).equals(BigInteger.ZERO) && @@ -2278,21 +2312,21 @@ public class XMLGregorianCalendarImpl // is a leap year. return 29; } else { - return daysInMonth[month]; + return DaysInMonth.table[month]; } } } private static int maximumDayInMonthFor(int year, int month) { if (month != DatatypeConstants.FEBRUARY) { - return daysInMonth[month]; + return DaysInMonth.table[month]; } else { if (((year % 400) == 0) || (((year % 100) != 0) && ((year % 4) == 0))) { // is a leap year. return 29; } else { - return daysInMonth[DatatypeConstants.FEBRUARY]; + return DaysInMonth.table[DatatypeConstants.FEBRUARY]; } } } @@ -2404,10 +2438,16 @@ public class XMLGregorianCalendarImpl result.setGregorianChange(PURE_GREGORIAN_CHANGE); // if year( and eon) are undefined, leave default Calendar values - BigInteger year = getEonAndYear(); - if (year != null) { - result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); - result.set(Calendar.YEAR, year.abs().intValue()); + if (year != DatatypeConstants.FIELD_UNDEFINED) { + if (eon == null) { + result.set(Calendar.ERA, year < 0 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, Math.abs(year)); + } + else { + BigInteger eonAndYear = getEonAndYear(); + result.set(Calendar.ERA, eonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, eonAndYear.abs().intValue()); + } } // only set month if it is set @@ -2543,16 +2583,31 @@ public class XMLGregorianCalendarImpl result.setGregorianChange(PURE_GREGORIAN_CHANGE); // if year( and eon) are undefined, leave default Calendar values - BigInteger year = getEonAndYear(); - if (year != null) { - result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); - result.set(Calendar.YEAR, year.abs().intValue()); + if (year != DatatypeConstants.FIELD_UNDEFINED) { + if (eon == null) { + result.set(Calendar.ERA, year < 0 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, Math.abs(year)); + } + else { + final BigInteger eonAndYear = getEonAndYear(); + result.set(Calendar.ERA, eonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, eonAndYear.abs().intValue()); + } } else { // use default if set - BigInteger defaultYear = (defaults != null) ? defaults.getEonAndYear() : null; - if (defaultYear != null) { - result.set(Calendar.ERA, defaultYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); - result.set(Calendar.YEAR, defaultYear.abs().intValue()); + if (defaults != null) { + final int defaultYear = defaults.getYear(); + if (defaultYear != DatatypeConstants.FIELD_UNDEFINED) { + if (defaults.getEon() == null) { + result.set(Calendar.ERA, defaultYear < 0 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, Math.abs(defaultYear)); + } + else { + final BigInteger defaultEonAndYear = defaults.getEonAndYear(); + result.set(Calendar.ERA, defaultEonAndYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); + result.set(Calendar.YEAR, defaultEonAndYear.abs().intValue()); + } + } } } @@ -2562,7 +2617,7 @@ public class XMLGregorianCalendarImpl result.set(Calendar.MONTH, month - 1); } else { // use default if set - int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED; + final int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED; if (defaultMonth != DatatypeConstants.FIELD_UNDEFINED) { // Calendar.MONTH is zero based while XMLGregorianCalendar month field is not. result.set(Calendar.MONTH, defaultMonth - 1); @@ -2574,7 +2629,7 @@ public class XMLGregorianCalendarImpl result.set(Calendar.DAY_OF_MONTH, day); } else { // use default if set - int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED; + final int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED; if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) { result.set(Calendar.DAY_OF_MONTH, defaultDay); } @@ -2596,7 +2651,7 @@ public class XMLGregorianCalendarImpl result.set(Calendar.MINUTE, minute); } else { // use default if set - int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED; + final int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED; if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) { result.set(Calendar.MINUTE, defaultMinute); } @@ -2607,7 +2662,7 @@ public class XMLGregorianCalendarImpl result.set(Calendar.SECOND, second); } else { // use default if set - int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED; + final int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED; if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) { result.set(Calendar.SECOND, defaultSecond); } @@ -2618,7 +2673,7 @@ public class XMLGregorianCalendarImpl result.set(Calendar.MILLISECOND, getMillisecond()); } else { // use default if set - BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null; + final BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null; if (defaultFractionalSecond != null) { result.set(Calendar.MILLISECOND, defaults.getMillisecond()); } @@ -2671,6 +2726,9 @@ public class XMLGregorianCalendarImpl customTimezoneId.append(sign); customTimezoneId.append(hour); if (minutes != 0) { + if (minutes < 10) { + customTimezoneId.append('0'); + } customTimezoneId.append(minutes); } result = TimeZone.getTimeZone(customTimezoneId.toString()); @@ -2718,7 +2776,7 @@ public class XMLGregorianCalendarImpl if(millisecond<0 || 999 - * I wrote a custom format method for a particular format string to - * see if it improves the performance, but it didn't. So this interpreting - * approach isn't too bad. - * - *

* StringBuffer -> StringBuilder change had a very visible impact. - * It almost cut the execution time to half, but unfortunately we can't use it - * because we need to run on JDK 1.3 + * It almost cut the execution time to half. + * Diff from Xerces: + * Xerces use StringBuffer due to the requirement to support + * JDKs older than JDK 1.5 */ private String format( String format ) { - char[] buf = new char[32]; - int bufPtr = 0; - + StringBuilder buf = new StringBuilder(); int fidx=0,flen=format.length(); while(fidx= 0) { - String zeros = frac.substring(pos+2); - frac = frac.substring(0,pos); - pos = frac.indexOf("."); - if (pos >= 0) { - frac = frac.substring(0,pos) + frac.substring(pos+1); + case 'Y': + if (eon == null) { + int absYear = year; + if (absYear < 0) { + buf.append('-'); + absYear = -year; } - int count = Integer.parseInt(zeros); - if (count < 40) { - frac = "00000000000000000000000000000000000000000".substring(0,count-1) + frac; - } else { - // do it the hard way - while (count > 1) { - frac = "0" + frac; - count--; - } + printNumber(buf, absYear, 4); + } + else { + printNumber(buf, getEonAndYear(), 4); + } + break; + case 'M': + printNumber(buf,getMonth(),2); + break; + case 'D': + printNumber(buf,getDay(),2); + break; + case 'h': + printNumber(buf,getHour(),2); + break; + case 'm': + printNumber(buf,getMinute(),2); + break; + case 's': + printNumber(buf,getSecond(),2); + if (getFractionalSecond() != null) { + //Xerces uses a custom method toString instead of + //toPlainString() since it needs to support JDKs older than 1.5 + String frac = getFractionalSecond().toPlainString(); + //skip leading zero. + buf.append(frac.substring(1, frac.length())); + } + break; + case 'z': + int offset = getTimezone(); + if (offset == 0) { + buf.append('Z'); + } + else if (offset != DatatypeConstants.FIELD_UNDEFINED) { + if (offset < 0) { + buf.append('-'); + offset *= -1; } - frac = "0." + frac; + else { + buf.append('+'); + } + printNumber(buf,offset/60,2); + buf.append(':'); + printNumber(buf,offset%60,2); } - - // reallocate the buffer now so that it has enough space - char[] n = new char[buf.length+frac.length()]; - System.arraycopy(buf,0,n,0,bufPtr); - buf = n; - //skip leading zero. - frac.getChars(1, frac.length(), buf, bufPtr); - bufPtr += frac.length()-1; - } - break; - case 'z': - int offset = getTimezone(); - if (offset == 0) { - buf[bufPtr++] = 'Z'; - } else - if (offset != DatatypeConstants.FIELD_UNDEFINED) { - if (offset < 0) { - buf[bufPtr++] = '-'; - offset *= -1; - } else { - buf[bufPtr++] = '+'; - } - bufPtr = print2Number(buf, bufPtr, offset / 60); - buf[bufPtr++] = ':'; - bufPtr = print2Number(buf, bufPtr, offset % 60); - } - break; - default: - throw new InternalError(); // impossible + break; + default: + throw new InternalError(); // impossible } } - return new String(buf,0,bufPtr); + return buf.toString(); } /** - * Prints an int as two digits into the buffer. + * Prints an integer as a String. * + * @param out + * The formatted string will be appended into this buffer. * @param number - * Number to be printed. Must be positive. + * The integer to be printed. + * @param nDigits + * The field will be printed by using at least this + * number of digits. For example, 5 will be printed as "0005" + * if nDigits==4. */ - private int print2Number( char[] out, int bufptr, int number ) { - out[bufptr++] = (char) ('0'+(number/10)); - out[bufptr++] = (char) ('0'+(number%10)); - return bufptr; + private void printNumber( StringBuilder out, int number, int nDigits ) { + String s = String.valueOf(number); + for (int i = s.length(); i < nDigits; i++) { + out.append('0'); + } + out.append(s); } /** - * Prints an int as four digits into the buffer. + * Prints an BigInteger as a String. * + * @param out + * The formatted string will be appended into this buffer. * @param number - * Number to be printed. Must be positive. + * The integer to be printed. + * @param nDigits + * The field will be printed by using at least this + * number of digits. For example, 5 will be printed as "0005" + * if nDigits==4. */ - private int print4Number( char[] out, int bufptr, int number ) { - out[bufptr+3] = (char) ('0'+(number%10)); - number /= 10; - out[bufptr+2] = (char) ('0'+(number%10)); - number /= 10; - out[bufptr+1] = (char) ('0'+(number%10)); - number /= 10; - out[bufptr ] = (char) ('0'+(number%10)); - return bufptr+4; + private void printNumber( StringBuilder out, BigInteger number, int nDigits) { + String s = number.toString(); + for (int i=s.length(); i < nDigits; i++) { + out.append('0'); + } + out.append(s); } /** @@ -3085,6 +3108,26 @@ public class XMLGregorianCalendarImpl * with the creation of new XMLGregorianCalendars.

*/ public void reset() { - //PENDING : Implementation of reset method + eon = orig_eon; + year = orig_year; + month = orig_month; + day = orig_day; + hour = orig_hour; + minute = orig_minute; + second = orig_second; + fractionalSecond = orig_fracSeconds; + timezone = orig_timezone; } + + /** Deserialize Calendar. */ + private void readObject(ObjectInputStream ois) + throws ClassNotFoundException, IOException { + + // perform default deseralization + ois.defaultReadObject(); + + // initialize orig_* fields + save(); + + } // readObject(ObjectInputStream) } From d0d3778b16eca1d8734f6f9249917a40d1aecf1c Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:43:21 -0800 Subject: [PATCH 078/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- jaxp/THIRD_PARTY_README | 1312 +++++++++++++++++++++++---------------- 1 file changed, 766 insertions(+), 546 deletions(-) diff --git a/jaxp/THIRD_PARTY_README b/jaxp/THIRD_PARTY_README index ee5463a922e..ba48858c28f 100644 --- a/jaxp/THIRD_PARTY_README +++ b/jaxp/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- From cde362cd0f90e17b16457699bb82bea25aa63945 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:43:36 -0800 Subject: [PATCH 079/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- jaxws/THIRD_PARTY_README | 1312 ++++++++++++++++++++++---------------- 1 file changed, 766 insertions(+), 546 deletions(-) diff --git a/jaxws/THIRD_PARTY_README b/jaxws/THIRD_PARTY_README index ee5463a922e..ba48858c28f 100644 --- a/jaxws/THIRD_PARTY_README +++ b/jaxws/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- From cf7f5c0b6115a2fefd27b0a9a11ec296515f770c Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 6 Feb 2014 15:49:51 +0000 Subject: [PATCH 080/265] 8033366: Add configure option to allow RMIConnector IIOP transport be selected compiled in or not Reviewed-by: erikj --- langtools/test/tools/javac/profiles/ProfileOptionTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/langtools/test/tools/javac/profiles/ProfileOptionTest.java b/langtools/test/tools/javac/profiles/ProfileOptionTest.java index fb0e1f60441..8314282f636 100644 --- a/langtools/test/tools/javac/profiles/ProfileOptionTest.java +++ b/langtools/test/tools/javac/profiles/ProfileOptionTest.java @@ -184,8 +184,7 @@ public class ProfileOptionTest { com.sun.security.auth.PolicyFile.class); // specifically included in 3 init(Profile.DEFAULT, - java.beans.BeanInfo.class, - javax.management.remote.rmi._RMIServer_Stub.class); // specifically excluded in 3 + java.beans.BeanInfo.class); } void init(Profile p, Class... classes) { From edee080e4ac584fe1d0fe6e10a1f47d80072fc0e Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Thu, 6 Feb 2014 18:49:01 +0000 Subject: [PATCH 081/265] 8030855: Default methods should be visible under source previous to 8 Reviewed-by: jjg, dlsmith --- .../com/sun/tools/javac/code/Source.java | 3 -- .../com/sun/tools/javac/comp/Resolve.java | 17 +++--- ...hodsNotVisibleForSourceLessThan8Test.java} | 54 ++++++++++++------- 3 files changed, 41 insertions(+), 33 deletions(-) rename langtools/test/tools/javac/{T8029240/DefaultMethodsNotVisibileForSource7Test.java => defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java} (75%) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java index 08c13b64940..ded0bb42a1f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java @@ -207,9 +207,6 @@ public enum Source { public boolean allowDefaultMethods() { return compareTo(JDK1_8) >= 0; } - public boolean allowDefaultMethodsResolution() { - return compareTo(JDK1_7) >= 0; - } public boolean allowStaticInterfaceMethods() { return compareTo(JDK1_8) >= 0; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index f0d709394d4..e3ea3cfe524 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -91,10 +91,9 @@ public class Resolve { TreeInfo treeinfo; Types types; JCDiagnostic.Factory diags; - public final boolean boxingEnabled; // = source.allowBoxing(); - public final boolean varargsEnabled; // = source.allowVarargs(); + public final boolean boxingEnabled; + public final boolean varargsEnabled; public final boolean allowMethodHandles; - public final boolean allowDefaultMethodsResolution; public final boolean allowStructuralMostSpecific; private final boolean debugResolve; private final boolean compactMethodDiags; @@ -136,7 +135,6 @@ public class Resolve { verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); Target target = Target.instance(context); allowMethodHandles = target.hasMethodHandles(); - allowDefaultMethodsResolution = source.allowDefaultMethodsResolution(); allowStructuralMostSpecific = source.allowStructuralMostSpecific(); polymorphicSignatureScope = new Scope(syms.noSymbol); @@ -1680,7 +1678,6 @@ public class Resolve { bestSoFar : methodNotFound; for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) { - if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && !allowDefaultMethodsResolution) break; //keep searching for abstract methods for (Type itype : itypes[iphase2.ordinal()]) { if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure()) @@ -1713,10 +1710,8 @@ public class Resolve { //from superinterfaces) if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) { return this; - } else if (rs.allowDefaultMethodsResolution) { - return DEFAULT_OK; } else { - return null; + return DEFAULT_OK; } } }, @@ -3340,9 +3335,9 @@ public class Resolve { if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; env1 = env1.outer; } - if (allowDefaultMethodsResolution && c.isInterface() && - name == names._super && !isStatic(env) && - types.isDirectSuperInterface(c, env.enclClass.sym)) { + if (c.isInterface() && + name == names._super && !isStatic(env) && + types.isDirectSuperInterface(c, env.enclClass.sym)) { //this might be a default super call if one of the superinterfaces is 'c' for (Type t : pruneInterfaces(env.enclClass.type)) { if (t.tsym == c) { diff --git a/langtools/test/tools/javac/T8029240/DefaultMethodsNotVisibileForSource7Test.java b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java similarity index 75% rename from langtools/test/tools/javac/T8029240/DefaultMethodsNotVisibileForSource7Test.java rename to langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java index 7a7516f6dfe..ea128931ab9 100644 --- a/langtools/test/tools/javac/T8029240/DefaultMethodsNotVisibileForSource7Test.java +++ b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,20 +23,21 @@ /* * @test - * @bug 8029240 + * @bug 8029240 8030855 * @summary Default methods not always visible under -source 7 + * Default methods should be visible under source previous to 8 * @library /tools/javac/lib * @build ToolBox - * @run main DefaultMethodsNotVisibileForSource7Test + * @run main DefaultMethodsNotVisibleForSourceLessThan8Test */ import java.nio.file.Files; import java.nio.file.Paths; -public class DefaultMethodsNotVisibileForSource7Test { +public class DefaultMethodsNotVisibleForSourceLessThan8Test { // common definitions - // this one should be compiled with source 8, the rest with source 7 + // this one should be compiled with source 8, the rest with source < 8 static final String ISrc = "interface I {\n" + " default void m() {}\n" + @@ -54,22 +55,22 @@ public class DefaultMethodsNotVisibileForSource7Test { // test legacy implementations static final String C1Src = "class C1 implements I {\n" + - " @Override public void m() {}\n" + + " public void m() {}\n" + "}"; static final String C2Src = "class C2 implements J {\n" + - " @Override public void m() {}\n" + + " public void m() {}\n" + "}"; static final String C3Src = "class C3 extends A {\n" + - " @Override public void m() {}\n" + + " public void m() {}\n" + "}"; static final String C4Src = "class C4 extends B {\n" + - " @Override public void m() {}\n" + + " public void m() {}\n" + "}"; //test legacy invocations @@ -99,10 +100,25 @@ public class DefaultMethodsNotVisibileForSource7Test { "}"; public static void main(String[] args) throws Exception { - new DefaultMethodsNotVisibileForSource7Test().run(); + String[] sources = new String[] { + "1.2", + "1.3", + "1.4", + "1.5", + "1.6", + "1.7", + }; + for (String source : sources) { + new DefaultMethodsNotVisibleForSourceLessThan8Test().run(source); + } } - void run() throws Exception { + String outDir; + String source; + + void run(String source) throws Exception { + this.source = source; + outDir = "out" + source.replace('.', '_'); testsPreparation(); testLegacyImplementations(); testLegacyInvocations(); @@ -110,27 +126,27 @@ public class DefaultMethodsNotVisibileForSource7Test { } void testsPreparation() throws Exception { - Files.createDirectory(Paths.get("out")); + Files.createDirectory(Paths.get(outDir)); /* as an extra check let's make sure that interface 'I' can't be compiled - * with source 7 + * with source < 8 */ ToolBox.JavaToolArgs javacArgs = new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-d", "out", "-source", "7") + .setOptions("-d", outDir, "-source", source) .setSources(ISrc); ToolBox.javac(javacArgs); //but it should compile with source >= 8 javacArgs = new ToolBox.JavaToolArgs() - .setOptions("-d", "out") + .setOptions("-d", outDir) .setSources(ISrc); ToolBox.javac(javacArgs); javacArgs = new ToolBox.JavaToolArgs() - .setOptions("-cp", "out", "-d", "out", "-source", "7") + .setOptions("-cp", outDir, "-d", outDir, "-source", source) .setSources(JSrc, ASrc, BSrc); ToolBox.javac(javacArgs); } @@ -139,7 +155,7 @@ public class DefaultMethodsNotVisibileForSource7Test { //compile C1-4 ToolBox.JavaToolArgs javacArgs = new ToolBox.JavaToolArgs() - .setOptions("-cp", "out", "-d", "out", "-source", "7") + .setOptions("-cp", outDir, "-d", outDir, "-source", source) .setSources(C1Src, C2Src, C3Src, C4Src); ToolBox.javac(javacArgs); } @@ -148,7 +164,7 @@ public class DefaultMethodsNotVisibileForSource7Test { //compile LegacyInvocation ToolBox.JavaToolArgs javacArgs = new ToolBox.JavaToolArgs() - .setOptions("-cp", "out", "-d", "out", "-source", "7") + .setOptions("-cp", outDir, "-d", outDir, "-source", source) .setSources(LegacyInvocationSrc); ToolBox.javac(javacArgs); } @@ -157,7 +173,7 @@ public class DefaultMethodsNotVisibileForSource7Test { //compile SubA, SubB ToolBox.JavaToolArgs javacArgs = new ToolBox.JavaToolArgs() - .setOptions("-cp", "out", "-d", "out", "-source", "7") + .setOptions("-cp", outDir, "-d", outDir, "-source", source) .setSources(SubASrc, SubBSrc); ToolBox.javac(javacArgs); } From 5b738090bd9ea94d90b422adfa445fa736aafe2b Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 6 Feb 2014 10:58:51 -0800 Subject: [PATCH 082/265] 8033686: Internal error for zero indent Reviewed-by: ksrini --- .../src/share/classes/com/sun/tools/javap/JavapTask.java | 8 ++++++-- .../src/share/classes/com/sun/tools/javap/Options.java | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java index 6033433d40e..4099f95d5cb 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java +++ b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java @@ -273,7 +273,9 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { void process(JavapTask task, String opt, String arg) throws BadArgs { int sep = opt.indexOf(":"); try { - task.options.indentWidth = Integer.valueOf(opt.substring(sep + 1)); + int i = Integer.valueOf(opt.substring(sep + 1)); + if (i > 0) // silently ignore invalid values + task.options.indentWidth = i; } catch (NumberFormatException e) { } } @@ -289,7 +291,9 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { void process(JavapTask task, String opt, String arg) throws BadArgs { int sep = opt.indexOf(":"); try { - task.options.tabColumn = Integer.valueOf(opt.substring(sep + 1)); + int i = Integer.valueOf(opt.substring(sep + 1)); + if (i > 0) // silently ignore invalid values + task.options.tabColumn = i; } catch (NumberFormatException e) { } } diff --git a/langtools/src/share/classes/com/sun/tools/javap/Options.java b/langtools/src/share/classes/com/sun/tools/javap/Options.java index fbfc30b2190..3723fc3afe0 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/Options.java +++ b/langtools/src/share/classes/com/sun/tools/javap/Options.java @@ -86,6 +86,6 @@ public class Options { public boolean showConstants; public boolean sysInfo; public boolean showInnerClasses; - public int indentWidth = 2; // #spaces per indentWidth level - public int tabColumn = 40; // column number for comments + public int indentWidth = 2; // #spaces per indentWidth level; must be > 0 + public int tabColumn = 40; // column number for comments; must be > 0 } From 47528ece5e23f88bfc69d4a702f22333a74dd8d1 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 6 Feb 2014 11:01:50 -0800 Subject: [PATCH 083/265] 8033711: An exception is thrown if using the \"-classpath\" option with no arguments Reviewed-by: ksrini --- .../com/sun/tools/javap/JavapTask.java | 8 ++- .../tools/javap/resources/javap.properties | 1 + langtools/test/tools/javap/T8033711.java | 55 +++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javap/T8033711.java diff --git a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java index 4099f95d5cb..e808989ecbe 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java +++ b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java @@ -529,8 +529,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { } } - if (fileManager.handleOption(name, rest)) - return; + try { + if (fileManager.handleOption(name, rest)) + return; + } catch (IllegalArgumentException e) { + throw new BadArgs("err.invalid.use.of.option", name).showUsage(true); + } throw new BadArgs("err.unknown.option", name).showUsage(true); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties b/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties index a704e7f5e51..3c5f78ee3ae 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties +++ b/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties @@ -13,6 +13,7 @@ err.ioerror=IO error reading {0}: {1} err.missing.arg=no value given for {0} err.no.classes.specified=no classes specified err.not.standard.file.manager=can only specify class files when using a standard file manager +err.invalid.use.of.option=invalid use of option: {0} err.unknown.option=unknown option: {0} err.no.SourceFile.attribute=no SourceFile attribute err.source.file.not.found=source file not found diff --git a/langtools/test/tools/javap/T8033711.java b/langtools/test/tools/javap/T8033711.java new file mode 100644 index 00000000000..e819146e2dc --- /dev/null +++ b/langtools/test/tools/javap/T8033711.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033711 + * @summary An exception is thrown if using the "-classpath" option with no arguments + */ + + +import java.io.*; + +public class T8033711 { + public static void main(String[] args) throws Exception { + new T8033711().run(); + } + + public void run() throws Exception { + String out = javap("-classpath"); + if (out.contains("IllegalArgumentException")) + throw new Exception("exception found in javap output"); + if (!out.contains("Error: invalid use of option")) + throw new Exception("expected error message not found in javap output"); + } + + String javap(String... args) { + StringWriter sw = new StringWriter(); + PrintWriter out = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, out); + out.close(); + System.out.println(sw.toString()); + System.out.println("javap exited, rc=" + rc); + return sw.toString(); + } +} From 8b3c6d6d4f13f5e09b148a256c2cc946ba988be2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 6 Feb 2014 15:43:23 -0800 Subject: [PATCH 084/265] 8033114: The values of non-static final fields are printed for the -constants option Reviewed-by: ksrini --- .../classes/com/sun/tools/javap/resources/javap.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties b/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties index 3c5f78ee3ae..861a676a990 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties +++ b/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties @@ -78,7 +78,7 @@ main.opt.bootclasspath=\ \ -bootclasspath Override location of bootstrap class files main.opt.constants=\ -\ -constants Show static final constants +\ -constants Show final constants main.opt.sysinfo=\ From 67d15f03e06859330605f5a34a7415b5515a8e0d Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Feb 2014 16:39:19 -0800 Subject: [PATCH 085/265] 8032526: fix the accessibility, html, syntax errors and warnings reported by doclint report in langtools Reviewed-by: jjg --- .../classes/com/sun/javadoc/package-info.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/langtools/src/share/classes/com/sun/javadoc/package-info.java b/langtools/src/share/classes/com/sun/javadoc/package-info.java index 15a0fd1af36..5fcc044d928 100644 --- a/langtools/src/share/classes/com/sun/javadoc/package-info.java +++ b/langtools/src/share/classes/com/sun/javadoc/package-info.java @@ -91,32 +91,32 @@ classes:
 import com.sun.javadoc.*;
 
-public class ListParams extends Doclet {
+public class ListParams extends Doclet {
 
-    public static boolean start(RootDoc root) {
-        ClassDoc[] classes = root.classes();
-        for (int i = 0; i < classes.length; ++i) {
-            ClassDoc cd = classes[i];
-            printMembers(cd.constructors());
-            printMembers(cd.methods());
+    public static boolean start(RootDoc root) {
+        ClassDoc[] classes = root.classes();
+        for (int i = 0; i < classes.length; ++i) {
+            ClassDoc cd = classes[i];
+            printMembers(cd.constructors());
+            printMembers(cd.methods());
         }
         return true;
     }
 
-    static void printMembers(ExecutableMemberDoc[] mems) {
-        for (int i = 0; i < mems.length; ++i) {
-            ParamTag[] params = mems[i].paramTags();
-            System.out.println(mems[i].qualifiedName());
-            for (int j = 0; j < params.length; ++j) {
-                System.out.println("   " + params[j].parameterName()
-                    + " - " + params[j].parameterComment());
+    static void printMembers(ExecutableMemberDoc[] mems) {
+        for (int i = 0; i < mems.length; ++i) {
+            ParamTag[] params = mems[i].paramTags();
+            System.out.println(mems[i].qualifiedName());
+            for (int j = 0; j < params.length; ++j) {
+                System.out.println("   " + params[j].parameterName()
+                    + " - " + params[j].parameterComment());
             }
         }
     }
 }
 
Interfaces and methods from the Javadoc API are marked in -red. +red. {@link com.sun.javadoc.Doclet Doclet} is an abstract class that specifies the invocation interface for doclets, {@link com.sun.javadoc.Doclet Doclet} holds class or interface information, From 29f985089ab0f7d6e6dd73844caa021ff08b0cb2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 6 Feb 2014 18:54:13 -0800 Subject: [PATCH 086/265] 8033581: Incorrect comment aligment 8033798: javap output has unnecessary trailing whitespace 8033726: StackMapTable does not unindent properly Reviewed-by: ksrini --- .../com/sun/tools/javap/AttributeWriter.java | 1 + .../com/sun/tools/javap/BasicWriter.java | 35 ++++--- .../test/tools/javap/MethodParameters.java | 24 ++--- .../test/tools/javap/WhitespaceTest.java | 93 +++++++++++++++++++ 4 files changed, 127 insertions(+), 26 deletions(-) create mode 100644 langtools/test/tools/javap/WhitespaceTest.java diff --git a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java index 49bdc467bac..8833e6937ee 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -603,6 +603,7 @@ public class AttributeWriter extends BasicWriter indent(+1); println("offset_delta = " + frame.offset_delta); printMap("locals", frame.locals); + indent(-1); return null; } diff --git a/langtools/src/share/classes/com/sun/tools/javap/BasicWriter.java b/langtools/src/share/classes/com/sun/tools/javap/BasicWriter.java index 4c2d92065bd..899bc415125 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/BasicWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/BasicWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,12 +151,22 @@ public class BasicWriter { for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { + case ' ': + pendingSpaces++; + break; + case '\n': println(); break; + default: if (buffer.length() == 0) indent(); + if (pendingSpaces > 0) { + for (int sp = 0; sp < pendingSpaces; sp++) + buffer.append(' '); + pendingSpaces = 0; + } buffer.append(c); } } @@ -164,6 +174,8 @@ public class BasicWriter { } protected void println() { + // ignore/discard pending spaces + pendingSpaces = 0; out.println(buffer); buffer.setLength(0); } @@ -173,26 +185,21 @@ public class BasicWriter { } protected void tab() { - if (buffer.length() == 0) - indent(); - space(indentCount * indentWidth + tabColumn - buffer.length()); + int col = indentCount * indentWidth + tabColumn; + pendingSpaces += (col <= buffer.length() ? 1 : col - buffer.length()); } private void indent() { - space(indentCount * indentWidth); + pendingSpaces += (indentCount * indentWidth); } - private void space(int n) { - for (int i = 0; i < n; i++) - buffer.append(' '); - } - - private PrintWriter out; - private StringBuilder buffer; + private final PrintWriter out; + private final StringBuilder buffer; private int indentCount; - private int indentWidth; - private int tabColumn; + private final int indentWidth; + private final int tabColumn; private boolean pendingNewline; + private int pendingSpaces; } } diff --git a/langtools/test/tools/javap/MethodParameters.java b/langtools/test/tools/javap/MethodParameters.java index 940724bf155..d9c427814f5 100644 --- a/langtools/test/tools/javap/MethodParameters.java +++ b/langtools/test/tools/javap/MethodParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,24 +44,24 @@ public class MethodParameters { static final String Init0_expected = (" Foo();\n" + " descriptor: ()V\n" + - " flags: \n" + + " flags:\n" + " Code:\n" + " stack=1, locals=1, args_size=1\n" + - " 0: aload_0 \n" + + " 0: aload_0\n" + " 1: invokespecial #1 // Method java/lang/Object.\"\":()V\n" + - " 4: return \n" + + " 4: return\n" + " LineNumberTable:\n" + " line 2: 0").replaceAll(" +", " "); static final String Init1_expected = (" Foo(int);\n" + " descriptor: (I)V\n" + - " flags: \n" + + " flags:\n" + " Code:\n" + " stack=1, locals=2, args_size=2\n" + - " 0: aload_0 \n" + + " 0: aload_0\n" + " 1: invokespecial #1 // Method java/lang/Object.\"\":()V\n" + - " 4: return \n" + + " 4: return\n" + " LineNumberTable:\n" + " line 3: 0\n" + " MethodParameters:\n" + @@ -71,25 +71,25 @@ public class MethodParameters { static final String foo0_expected = (" void foo0();\n" + " descriptor: ()V\n" + - " flags: \n" + + " flags:\n" + " Code:\n" + " stack=0, locals=1, args_size=1\n" + - " 0: return \n" + + " 0: return\n" + " LineNumberTable:\n" + " line 4: 0").replaceAll(" +", " "); static final String foo2_expected = (" void foo2(int, int);\n" + " descriptor: (II)V\n" + - " flags: \n" + + " flags:\n" + " Code:\n" + " stack=0, locals=3, args_size=3\n" + - " 0: return \n" + + " 0: return\n" + " LineNumberTable:\n" + " line 5: 0\n" + " MethodParameters:\n" + " Name Flags\n" + - " j \n" + + " j\n" + " k").replaceAll(" +", " "); static final File classesdir = new File("methodparameters"); diff --git a/langtools/test/tools/javap/WhitespaceTest.java b/langtools/test/tools/javap/WhitespaceTest.java new file mode 100644 index 00000000000..3c9933a33e2 --- /dev/null +++ b/langtools/test/tools/javap/WhitespaceTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033581 8033798 8033726 + * @summary Check whitespace in generated output + */ + +import java.io.*; +import java.util.*; + +public class WhitespaceTest { + public static void main(String... args) throws Exception { + new WhitespaceTest().run(); + } + + void run() throws Exception { + test("-v", "java.lang.String"); + test("-XDtab:1", "-v", "java.lang.String"); + + String testClasses = System.getProperty("test.classes"); + for (int i = 10; i < 40; i++) + test("-XDtab:" + i, "-v", "-classpath", testClasses, "WhitespaceTest$HelloWorld"); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void test(String... args) throws Exception { + // need to avoid "//" appearing as a constant in the constant pool + String slash = "/"; + String doubleSlash = slash + slash; + System.out.println("test: " + Arrays.asList(args)); + String out = javap(args); + for (String line: out.split("[\r\n]+")) { + if (line.endsWith(" ")) + error("line has trailing whitespace: " + line); + int comment = line.indexOf(doubleSlash); + if (comment > 0 && line.charAt(comment - 1) != ' ') + error("no space before comment: " + line); + if (line.matches(" +}")) + error("bad indentation: " + line); + } + } + + String javap(String... args) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter out = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, out); + out.close(); + System.out.println(sw.toString()); + if (rc < 0) + throw new Exception("javap exited, rc=" + rc); + return sw.toString(); + } + + void error(String msg) { + System.out.println("Error: " + msg); + errors++; + } + + int errors; + + // small class to test repeatedly with different tab values + static class HelloWorld { + public static void main(String... args) { + System.out.println("Hello World!"); + } + } +} + + From c0d767f6f1a8bb3422329e89e2c0cfe07d5b5192 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 7 Feb 2014 21:43:33 +0100 Subject: [PATCH 087/265] 8033421: @SuppressWarnings("deprecation") does not work when overriding deprecated method When the overrides deprecated method warning is being reported, need to do that in the lint context of the method. Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Check.java | 7 +++- .../javac/warnings/suppress/Overridden.java | 16 ++++++++ .../javac/warnings/suppress/Overridden.out | 2 + .../suppress/OverriddenSuppressed.java | 38 +++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/warnings/suppress/Overridden.java create mode 100644 langtools/test/tools/javac/warnings/suppress/Overridden.out create mode 100644 langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index e44c6ddc586..1bec67e8a0c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1705,7 +1705,12 @@ public class Check { // Warn if a deprecated method overridden by a non-deprecated one. if (!isDeprecatedOverrideIgnorable(other, origin)) { - checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other); + Lint prevLint = setLint(lint.augment(m)); + try { + checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other); + } finally { + setLint(prevLint); + } } } // where diff --git a/langtools/test/tools/javac/warnings/suppress/Overridden.java b/langtools/test/tools/javac/warnings/suppress/Overridden.java new file mode 100644 index 00000000000..8366e395dfe --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/Overridden.java @@ -0,0 +1,16 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8033421 + * @summary Check that \\@SuppressWarnings works properly when overriding deprecated method. + * @build VerifySuppressWarnings + * @compile/ref=Overridden.out -XDrawDiagnostics -Xlint:deprecation Overridden.java + * @run main VerifySuppressWarnings Overridden.java + */ + +public class Overridden implements Interface { + public void test() { } +} + +interface Interface { + @Deprecated void test(); +} diff --git a/langtools/test/tools/javac/warnings/suppress/Overridden.out b/langtools/test/tools/javac/warnings/suppress/Overridden.out new file mode 100644 index 00000000000..a215218b9d7 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/Overridden.out @@ -0,0 +1,2 @@ +Overridden.java:11:17: compiler.warn.has.been.deprecated: test(), Interface +1 warning diff --git a/langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java b/langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java new file mode 100644 index 00000000000..4d2e305e395 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8033421 + * @summary Check that \\@SuppressWarnings works properly when overriding deprecated method. + * @compile -Werror -Xlint:deprecation OverriddenSuppressed.java + */ + +public class OverriddenSuppressed implements Interface { + @SuppressWarnings("deprecation") + public void test() { } +} + +interface Interface { + @Deprecated void test(); +} From 4e86ae998841f252f7ff0be59a1d5c4724ccb86c Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 10 Feb 2014 11:52:52 -0800 Subject: [PATCH 088/265] 8033930: Unnecessary new line after the StackMapTable 8033913: Incorrect indentation of StackMapTable entries Reviewed-by: ksrini --- .../com/sun/tools/javap/AttributeWriter.java | 30 +++--- .../test/tools/javap/StackMapTableTest.java | 92 +++++++++++++++++++ 2 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 langtools/test/tools/javap/StackMapTableTest.java diff --git a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java index 8833e6937ee..fb43a3c75f7 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -531,7 +531,6 @@ public class AttributeWriter extends BasicWriter for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { w.write(entry); } - println(); indent(-1); return null; } @@ -543,7 +542,6 @@ public class AttributeWriter extends BasicWriter for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { w.write(entry); } - println(); indent(-1); return null; } @@ -555,14 +553,12 @@ public class AttributeWriter extends BasicWriter } public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) { - printHeader(frame); - println(" /* same */"); + printHeader(frame, "/* same */"); return null; } public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) { - printHeader(frame); - println(" /* same_locals_1_stack_item */"); + printHeader(frame, "/* same_locals_1_stack_item */"); indent(+1); printMap("stack", frame.stack); indent(-1); @@ -570,8 +566,7 @@ public class AttributeWriter extends BasicWriter } public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) { - printHeader(frame); - println(" /* same_locals_1_stack_item_frame_extended */"); + printHeader(frame, "/* same_locals_1_stack_item_frame_extended */"); indent(+1); println("offset_delta = " + frame.offset_delta); printMap("stack", frame.stack); @@ -580,8 +575,7 @@ public class AttributeWriter extends BasicWriter } public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) { - printHeader(frame); - println(" /* chop */"); + printHeader(frame, "/* chop */"); indent(+1); println("offset_delta = " + frame.offset_delta); indent(-1); @@ -589,8 +583,7 @@ public class AttributeWriter extends BasicWriter } public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) { - printHeader(frame); - println(" /* same_frame_extended */"); + printHeader(frame, "/* same_frame_extended */"); indent(+1); println("offset_delta = " + frame.offset_delta); indent(-1); @@ -598,8 +591,7 @@ public class AttributeWriter extends BasicWriter } public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) { - printHeader(frame); - println(" /* append */"); + printHeader(frame, "/* append */"); indent(+1); println("offset_delta = " + frame.offset_delta); printMap("locals", frame.locals); @@ -608,12 +600,11 @@ public class AttributeWriter extends BasicWriter } public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) { - printHeader(frame); if (frame instanceof StackMap_attribute.stack_map_frame) { + printHeader(frame, "offset = " + frame.offset_delta); indent(+1); - println(" offset = " + frame.offset_delta); } else { - println(" /* full_frame */"); + printHeader(frame, "/* full_frame */"); indent(+1); println("offset_delta = " + frame.offset_delta); } @@ -623,8 +614,9 @@ public class AttributeWriter extends BasicWriter return null; } - void printHeader(StackMapTable_attribute.stack_map_frame frame) { - print(" frame_type = " + frame.frame_type); + void printHeader(StackMapTable_attribute.stack_map_frame frame, String extra) { + print("frame_type = " + frame.frame_type + " "); + println(extra); } void printMap(String name, StackMapTable_attribute.verification_type_info[] map) { diff --git a/langtools/test/tools/javap/StackMapTableTest.java b/langtools/test/tools/javap/StackMapTableTest.java new file mode 100644 index 00000000000..97e19ac9e16 --- /dev/null +++ b/langtools/test/tools/javap/StackMapTableTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033930 8033913 + * @summary bad formatting of StackMapTable entries + */ + +import java.io.*; +import java.util.*; + +public class StackMapTableTest { + public static void main(String... args) throws Exception { + new StackMapTableTest().run(); + } + + void run() throws Exception { + String testClasses = System.getProperty("test.classes"); + String out = javap("-v", "-classpath", testClasses, A.class.getName()); + + String nl = System.getProperty("line.separator"); + out = out.replaceAll(nl, "\n"); + + if (out.contains("\n\n\n")) + error("double blank line found"); + + String expect = + " StackMapTable: number_of_entries = 2\n" + + " frame_type = 252 /* append */\n" + + " offset_delta = 2\n" + + " locals = [ int ]\n" + + " frame_type = 250 /* chop */\n" + + " offset_delta = 18\n"; + if (!out.contains(expect)) + error("expected text not found"); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + String javap(String... args) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter out = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, out); + out.close(); + System.out.println(sw.toString()); + if (rc < 0) + throw new Exception("javap exited, rc=" + rc); + return sw.toString(); + } + + void error(String msg) { + System.out.println("Error: " + msg); + errors++; + } + + int errors; + + /** Simple test class to run through javap. */ + public class A { + public void a() { + for (int i = 0; i < 10; i++) { + System.out.println(i); + } + } + public void b() { + } + public void c() { + } + } +} From 55801d06ffac894992097aabcb4631e284f70219 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 12 Feb 2014 12:31:30 -0700 Subject: [PATCH 089/265] 4910483: Javadoc renders the string ".*\\.pdf" as ".\*\.pdf" Adjust timing of printing "\\" in the comment scanner Reviewed-by: jjg --- .../tools/javac/parser/JavadocTokenizer.java | 20 ++++++- .../test/tools/javac/parser/T4910483.java | 59 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/parser/T4910483.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java index 367345a7fff..06f249188eb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java @@ -107,6 +107,10 @@ public class JavadocTokenizer extends JavaTokenizer { */ int pp = 0; + /** The buffer index of the last double backslash sequence + */ + private int doubleBackslashBp = -1; + DocReader(ScannerFactory fac, char[] input, int inputLength, int startPos) { super(fac, input, inputLength); this.startPos = startPos; @@ -149,8 +153,8 @@ public class JavadocTokenizer extends JavaTokenizer { scanChar(); if (ch == '\\') { if (peekChar() == '\\' && !isUnicode()) { - putChar(ch, false); bp++; col++; + doubleBackslashBp = bp; } else { convertUnicode(); } @@ -204,6 +208,13 @@ public class JavadocTokenizer extends JavaTokenizer { } super.putChar(ch, scan); } + + /** Whether the ch represents a sequence of two backslashes. */ + boolean isDoubleBackslash() { + return doubleBackslashBp == bp; + } + + } protected static class JavadocComment extends JavaTokenizer.BasicComment { @@ -375,6 +386,13 @@ public class JavadocTokenizer extends JavaTokenizer { // the buffer. comment_reader.putChar('*', false); break; + case '\\': + comment_reader.putChar('\\', false); + // If a double backslash was found, write two + if (comment_reader.isDoubleBackslash()) { + comment_reader.putChar('\\', false); + } + comment_reader.scanCommentChar(); case ' ': case '\t': comment_reader.putChar(comment_reader.ch, false); diff --git a/langtools/test/tools/javac/parser/T4910483.java b/langtools/test/tools/javac/parser/T4910483.java new file mode 100644 index 00000000000..7d80e0ade5d --- /dev/null +++ b/langtools/test/tools/javac/parser/T4910483.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 4910483 + * @summary javac shouldn't throw NPE while compiling invalid RuntimeInvisibleParameterAnnotations + * @run main T4910483 + */ + +import java.io.File; + +import com.sun.tools.javac.main.JavaCompiler; +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.Context; + +import javax.tools.JavaFileObject; + +/**Test comment abc*\\def*/ +public class T4910483 { + public static void main(String... args) { + JavaCompiler compiler = JavaCompiler.instance(new Context()); + compiler.keepComments = true; + + String testSrc = System.getProperty("test.src"); + JavacFileManager fm = new JavacFileManager(new Context(), false, null); + JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + "T4910483.java"); + + JCTree.JCCompilationUnit cu = compiler.parse(f); + JCTree classDef = cu.getTypeDecls().head; + String commentText = cu.docComments.getCommentText(classDef); + + String expected = "Test comment abc*\\\\def"; // 4 '\' escapes to 2 in a string literal + if (!expected.equals(commentText)) { + throw new AssertionError("Incorrect comment text: [" + commentText + "], expected [" + expected + "]"); + } + } +} From e20546fe2accb464dd85c0ba28535f82ab32d9d2 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 13 Feb 2014 13:38:48 +0100 Subject: [PATCH 090/265] 8033961: Formatting of -Xlint: command line help Improving formatting of command line help for -Xlint, including a short description of each lint. Reviewed-by: jjg --- .../com/sun/tools/javac/main/Option.java | 42 ++++++++-- .../tools/javac/resources/javac.properties | 78 ++++++++++++++++++- .../tools/javac/diags/CheckResourceKeys.java | 18 ++++- .../warnings/VerifyLintDescriptions.java | 58 ++++++++++++++ 4 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 langtools/test/tools/javac/warnings/VerifyLintDescriptions.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java index ab2bc6af954..6ecf168d894 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import javax.lang.model.SourceVersion; import com.sun.tools.doclint.DocLint; import com.sun.tools.javac.code.Lint; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.jvm.Profile; @@ -80,8 +81,34 @@ public enum Option { XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC), - XLINT_CUSTOM("-Xlint:", "opt.Xlint.suboptlist", - EXTENDED, BASIC, ANYOF, getXLintChoices()), + XLINT_CUSTOM("-Xlint:", EXTENDED, BASIC, ANYOF, getXLintChoices()) { + private static final String LINT_KEY_FORMAT = " %-19s %s"; + void help(Log log, OptionKind kind) { + if (this.kind != kind) + return; + + log.printRawLines(WriterKind.NOTICE, + String.format(HELP_LINE_FORMAT, + log.localize(PrefixKind.JAVAC, "opt.Xlint.subopts"), + log.localize(PrefixKind.JAVAC, "opt.Xlint.suboptlist"))); + log.printRawLines(WriterKind.NOTICE, + String.format(LINT_KEY_FORMAT, + "all", + log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); + for (LintCategory lc : LintCategory.values()) { + if (lc.hidden) continue; + log.printRawLines(WriterKind.NOTICE, + String.format(LINT_KEY_FORMAT, + lc.option, + log.localize(PrefixKind.JAVAC, + "opt.Xlint.desc." + lc.option))); + } + log.printRawLines(WriterKind.NOTICE, + String.format(LINT_KEY_FORMAT, + "none", + log.localize(PrefixKind.JAVAC, "opt.Xlint.none"))); + } + }, XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC), @@ -550,10 +577,9 @@ public enum Option { this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix); } - Option(String text, String descrKey, - OptionKind kind, OptionGroup group, + Option(String text, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map choices) { - this(text, null, descrKey, kind, group, choiceKind, choices, false); + this(text, null, null, kind, group, choiceKind, choices, false); } Option(String text, String descrKey, @@ -650,12 +676,14 @@ public enum Option { return process(helper, option, option); } + private static final String HELP_LINE_FORMAT = " %-26s %s"; + void help(Log log, OptionKind kind) { if (this.kind != kind) return; log.printRawLines(WriterKind.NOTICE, - String.format(" %-26s %s", + String.format(HELP_LINE_FORMAT, helpSynopsis(log), log.localize(PrefixKind.JAVAC, descrKey))); diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties index 328d9fbf76b..eba8345038c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -142,8 +142,80 @@ javac.opt.arg.file=\ javac.opt.Xlint=\ Enable recommended warnings -javac.opt.Xlint.suboptlist=\ - Enable or disable specific warnings +javac.opt.Xlint.all=\ + Enable all warnings +javac.opt.Xlint.none=\ + Disable all warnings +#L10N: do not localize: -Xlint +javac.opt.Xlint.subopts=\ + -Xlint:key,... +javac.opt.Xlint.suboptlist=\n\ +\ Warnings to enable or disable, separated by comma.\n\ +\ Precede a key by '-' to disable the specified warning.\n\ +\ Supported keys are: +javac.opt.Xlint.desc.auxiliaryclass=\ + Warn about an auxiliary class that is hidden in a source file, and is used from other files. + +javac.opt.Xlint.desc.cast=\ + Warn about use of unnecessary casts. + +javac.opt.Xlint.desc.classfile=\ + Warn about issues related to classfile contents. + +javac.opt.Xlint.desc.deprecation=\ + Warn about use of deprecated items. + +javac.opt.Xlint.desc.dep-ann=\ + Warn about items marked as deprecated in JavaDoc but not using the @Deprecated annotation. + +javac.opt.Xlint.desc.divzero=\ + Warn about division by constant integer 0. + +javac.opt.Xlint.desc.empty=\ + Warn about empty statement after if. + +javac.opt.Xlint.desc.fallthrough=\ + Warn about falling through from one case of a switch statement to the next. + +javac.opt.Xlint.desc.finally=\ + Warn about finally clauses that do not terminate normally. + +javac.opt.Xlint.desc.options=\ + Warn about issues relating to use of command line options. + +javac.opt.Xlint.desc.overloads=\ + Warn about issues regarding method overloads. + +javac.opt.Xlint.desc.overrides=\ + Warn about issues regarding method overrides. + +javac.opt.Xlint.desc.path=\ + Warn about invalid path elements on the command line. + +javac.opt.Xlint.desc.processing=\ + Warn about issues regarding annotation processing. + +javac.opt.Xlint.desc.rawtypes=\ + Warn about use of raw types. + +javac.opt.Xlint.desc.serial=\ + Warn about Serializable classes that do not provide a serial version ID. + +javac.opt.Xlint.desc.static=\ + Warn about accessing a static member using an instance. + +javac.opt.Xlint.desc.sunapi=\ + Warn about proprietary API that may be removed in a future release. + +javac.opt.Xlint.desc.try=\ + Warn about issues relating to use of try blocks (i.e. try-with-resources). + +javac.opt.Xlint.desc.unchecked=\ + Warn about unchecked operations. + +javac.opt.Xlint.desc.varargs=\ + Warn about potentially unsafe vararg methods + javac.opt.Xdoclint=\ Enable recommended checks for problems in javadoc comments # L10N: do not localize: all none diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index bb9e10bd7cf..5f7f5c3ea41 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.io.*; import java.util.*; import javax.tools.*; import com.sun.tools.classfile.*; +import com.sun.tools.javac.code.Lint.LintCategory; /** * Compare string constants in javac classes against keys in javac resource bundles. @@ -156,6 +157,20 @@ public class CheckResourceKeys { if (needToInvestigate.contains(rk)) continue; + //check lint description keys: + if (s.startsWith("opt.Xlint.desc.")) { + String option = s.substring(15); + boolean found = false; + + for (LintCategory lc : LintCategory.values()) { + if (option.equals(lc.option)) + found = true; + } + + if (found) + continue; + } + error("Resource key not found in code: " + rk); } } @@ -274,6 +289,7 @@ public class CheckResourceKeys { // prefix/embedded strings "compiler.", "compiler.misc.", + "opt.Xlint.desc.", "count.", "illegal.", "javac.", diff --git a/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java b/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java new file mode 100644 index 00000000000..b7bc6980ec8 --- /dev/null +++ b/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8033961 + * @summary Verify that all LintCategories have their descriptions filled. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import com.sun.tools.javac.code.Lint.LintCategory; +import com.sun.tools.javac.util.Log.PrefixKind; + +public class VerifyLintDescriptions { + public static void main(String... args) { + ResourceBundle b = ResourceBundle.getBundle("com.sun.tools.javac.resources.javac", + Locale.US); + + List missing = new ArrayList<>(); + + for (LintCategory lc : LintCategory.values()) { + try { + b.getString(PrefixKind.JAVAC.key("opt.Xlint.desc." + lc.option)); + } catch (MissingResourceException ex) { + missing.add(lc.option); + } + } + + if (!missing.isEmpty()) { + throw new UnsupportedOperationException("Lints that are missing description: " + missing); + } + } + +} From 8daec20c869ff20ec0a7974666310bd4cb2bc46a Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Thu, 13 Feb 2014 14:58:10 +0100 Subject: [PATCH 091/265] 8030714: The steps attribute, flow and desugar are unnecessary for implicit classes when compiling with -implicit:none When compiling with -implicit:none, attribute, flow and desugar is skipped for better performance. Reviewed-by: jfranck, jlahoda --- .../com/sun/tools/javac/comp/Todo.java | 22 +++++++++++++++-- .../sun/tools/javac/main/JavaCompiler.java | 8 ++++++- .../tools/javac/implicitCompile/Implicit.java | 24 +++++++++++++++++++ .../SkipAttrFlowGenForImplicits.java | 9 +++++++ .../SkipAttrFlowGenForImplicits.out | 4 ++++ 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 langtools/test/tools/javac/implicitCompile/Implicit.java create mode 100644 langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.java create mode 100644 langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java index 3a91150d529..eaeef343370 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package com.sun.tools.javac.comp; import java.util.AbstractQueue; -import com.sun.tools.javac.util.Context; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -34,6 +34,8 @@ import java.util.Map; import java.util.Queue; import javax.tools.JavaFileObject; +import com.sun.tools.javac.util.Context; + /** A queue of all as yet unattributed classes. * *

This is NOT part of any supported API. @@ -82,6 +84,22 @@ public class Todo extends AbstractQueue> { } } + /** + * Removes all unattributed classes except those belonging to the given + * collection of files. + * + * @param sourceFiles The source files of the classes to keep. + */ + public void retainFiles(Collection sourceFiles) { + for (Iterator> it = contents.iterator(); it.hasNext(); ) { + Env env = it.next(); + if (!sourceFiles.contains(env.toplevel.sourcefile)) { + if (contentsByFile != null) removeByFile(env); + it.remove(); + } + } + } + public Env poll() { if (size() == 0) return null; diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index a244dcfa0bc..cd30dbcd0df 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -856,6 +856,12 @@ public class JavaCompiler { enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); + // If it's safe to do so, skip attr / flow / gen for implicit classes + if (taskListener.isEmpty() && + implicitSourcePolicy == ImplicitSourcePolicy.NONE) { + delegateCompiler.todo.retainFiles(delegateCompiler.inputFiles); + } + delegateCompiler.compile2(); delegateCompiler.close(); elapsed_msec = delegateCompiler.elapsed_msec; diff --git a/langtools/test/tools/javac/implicitCompile/Implicit.java b/langtools/test/tools/javac/implicitCompile/Implicit.java new file mode 100644 index 00000000000..4a36d896ffa --- /dev/null +++ b/langtools/test/tools/javac/implicitCompile/Implicit.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +class Implicit { +} diff --git a/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.java b/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.java new file mode 100644 index 00000000000..6f8004a11fe --- /dev/null +++ b/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.java @@ -0,0 +1,9 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8030714 + * @summary make sure attribute and flow is skipped for implicit classes + * @compile/ref=SkipAttrFlowGenForImplicits.out -XDverboseCompilePolicy -implicit:none SkipAttrFlowGenForImplicits.java + */ +class Explicit { + Implicit implicit; +} diff --git a/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out b/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out new file mode 100644 index 00000000000..11cc81304f0 --- /dev/null +++ b/langtools/test/tools/javac/implicitCompile/SkipAttrFlowGenForImplicits.out @@ -0,0 +1,4 @@ +[attribute Explicit] +[flow Explicit] +[desugar Explicit] +[generate code Explicit] From c7480b651353f305742c6ebfd795ad42fbb2b7dc Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 14 Feb 2014 17:28:07 -0800 Subject: [PATCH 092/265] 8029145: javadoc fails with java.lang.IllegalStateException: endPosTable already set Reviewed-by: jjg --- .../com/sun/tools/javadoc/JavadocTool.java | 12 +++++++---- .../javadoc/parser/7091528/T7091528.java | 21 ++++++++++++------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java index 58b22415eae..a80b1a26802 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.IOException; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.tools.JavaFileManager.Location; @@ -238,10 +239,13 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { files = lb.toList(); } + Set ufiles = new HashSet<>(); for (JavaFileObject fo : files) { - // messager.notice("main.Loading_source_file", fn); - trees.append(parse(fo)); - hasFiles = true; + if (ufiles.add(fo)) { // ignore duplicates + // messager.notice("main.Loading_source_file", fn); + trees.append(parse(fo)); + hasFiles = true; + } } if (!hasFiles) { diff --git a/langtools/test/tools/javadoc/parser/7091528/T7091528.java b/langtools/test/tools/javadoc/parser/7091528/T7091528.java index 4e06a3beb74..b491073d7c7 100644 --- a/langtools/test/tools/javadoc/parser/7091528/T7091528.java +++ b/langtools/test/tools/javadoc/parser/7091528/T7091528.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,8 @@ /** * @test - * @bug 7091528 - * @summary javadoc attempts to parse .class files + * @bug 7091528 8029145 + * @summary ensures javadoc parses unique source files and ignores all class files * @compile p/C1.java p/q/C2.java * @run main T7091528 */ @@ -37,17 +37,22 @@ public class T7091528 { public static void main(String... args) { new T7091528().run(); } - void run() { File testSrc = new File(System.getProperty("test.src")); File testClasses = new File(System.getProperty("test.classes")); - String[] args = { - "-d", ".", + // 7091528, tests if class files are being ignored + runTest("-d", ".", "-sourcepath", testClasses + File.pathSeparator + testSrc, "-subpackages", - "p" - }; + "p"); + // 8029145, tests if unique source files are parsed + runTest("-d", ".", + "-sourcepath", testSrc.getAbsolutePath(), + "-subpackages", + "p:p.q"); + } + void runTest(String... args) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); String doclet = com.sun.tools.doclets.standard.Standard.class.getName(); From f643b8cab061ee01ffa8d4ffb418ae42896f43e1 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Sat, 15 Feb 2014 16:37:19 -0800 Subject: [PATCH 093/265] 8031545: [javac] refactor and cleanup JNIWriter.java Reviewed-by: jjg --- .../com/sun/tools/javac/jvm/JNIWriter.java | 974 +++++++----------- .../javahComparison/CompareTest.java | 2 +- .../javahComparison/TestClass1.java | 164 +-- 3 files changed, 485 insertions(+), 655 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java index 4fc9987d69e..b12adc0ab6c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,30 +26,10 @@ package com.sun.tools.javac.jvm; import java.io.IOException; -import java.io.Writer; +import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Stack; -import java.util.StringTokenizer; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.NoType; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.TypeVisitor; -import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; -import javax.lang.model.util.SimpleTypeVisitor8; -import javax.lang.model.util.Types; import javax.tools.FileObject; import javax.tools.JavaFileManager; @@ -57,18 +37,22 @@ import javax.tools.StandardLocation; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Symbol; 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.model.JavacElements; -import com.sun.tools.javac.model.JavacTypes; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Options; +import com.sun.tools.javac.util.Pair; import static com.sun.tools.javac.main.Option.*; +import static com.sun.tools.javac.code.Kinds.*; /** This class provides operations to write native header files for classes. * @@ -83,8 +67,8 @@ public class JNIWriter { /** Access to files. */ private final JavaFileManager fileManager; - JavacElements elements; - JavacTypes types; + Types types; + Symtab syms; /** The log to use for verbose output. */ @@ -98,15 +82,9 @@ public class JNIWriter { */ private boolean checkAll; - private Mangle mangler; - private Context context; - private Symtab syms; - - private String lineSep; - - private final boolean isWindows = + private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); /** Get the ClassWriter instance for this context. */ @@ -129,44 +107,58 @@ public class JNIWriter { checkAll = options.isSet("javah:full"); this.context = context; // for lazyInit() - syms = Symtab.instance(context); - - lineSep = System.getProperty("line.separator"); } private void lazyInit() { - if (mangler == null) { - elements = JavacElements.instance(context); - types = JavacTypes.instance(context); - mangler = new Mangle(elements, types); - } + if (types == null) + types = Types.instance(context); + if (syms == null) + syms = Symtab.instance(context); + + } + + static boolean isSynthetic(Symbol s) { + return hasFlag(s, Flags.SYNTHETIC); + } + static boolean isStatic(Symbol s) { + return hasFlag(s, Flags.STATIC); + } + static boolean isFinal(Symbol s) { + return hasFlag(s, Flags.FINAL); + } + static boolean isNative(Symbol s) { + return hasFlag(s, Flags.NATIVE); + } + static private boolean hasFlag(Symbol m, int flag) { + return (m.flags() & flag) != 0; } public boolean needsHeader(ClassSymbol c) { - if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0) + lazyInit(); + if (c.isLocal() || isSynthetic(c)) return false; - - if (checkAll) - return needsHeader(c.outermostClass(), true); - else - return needsHeader(c, false); + return (checkAll) + ? needsHeader(c.outermostClass(), true) + : needsHeader(c, false); } private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) { - if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0) + if (c.isLocal() || isSynthetic(c)) return false; for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) { - if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0) + Symbol sym = i.sym; + if (sym.kind == MTH && isNative(sym)) return true; - for (Attribute.Compound a: i.sym.getDeclarationAttributes()) { + for (Attribute.Compound a: sym.getDeclarationAttributes()) { if (a.type.tsym == syms.nativeHeaderType.tsym) return true; } } if (checkNestedClasses) { for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) { - if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true)) + Symbol sym = i.sym; + if ((sym.kind == TYP) && needsHeader(((ClassSymbol) sym), true)) return true; } } @@ -176,14 +168,12 @@ public class JNIWriter { /** Emit a class file for a given class. * @param c The class from which a class file is generated. */ - public FileObject write(ClassSymbol c) - throws IOException - { + public FileObject write(ClassSymbol c) throws IOException { String className = c.flatName().toString(); FileObject outFile = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT, "", className.replaceAll("[.$]", "_") + ".h", null); - Writer out = outFile.openWriter(); + PrintWriter out = new PrintWriter(outFile.openWriter()); try { write(out, c); if (verbose) @@ -201,201 +191,134 @@ public class JNIWriter { return outFile; // may be null if write failed } - public void write(Writer out, ClassSymbol sym) - throws IOException { + public void write(PrintWriter out, ClassSymbol sym) throws IOException { lazyInit(); try { - String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS); - println(out, fileTop()); - println(out, includes()); - println(out, guardBegin(cname)); - println(out, cppGuardBegin()); + String cname = encode(sym.fullname, EncoderType.CLASS); + fileTop(out); + includes(out); + guardBegin(out, cname); + cppGuardBegin(out); writeStatics(out, sym); writeMethods(out, sym, cname); - println(out, cppGuardEnd()); - println(out, guardEnd(cname)); + cppGuardEnd(out); + guardEnd(out); } catch (TypeSignature.SignatureException e) { throw new IOException(e); } } - - protected void writeStatics(Writer out, ClassSymbol sym) throws IOException { - List classfields = getAllFields(sym); - - for (VariableElement v: classfields) { - if (!v.getModifiers().contains(Modifier.STATIC)) - continue; - String s = null; - s = defineForStatic(sym, v); - if (s != null) { - println(out, s); + protected void writeStatics(PrintWriter out, ClassSymbol sym) throws IOException { + List clist = new ArrayList<>(); + for (ClassSymbol cd = sym; cd != null; + cd = (ClassSymbol) cd.getSuperclass().tsym) { + clist.add(cd); + } + /* + * list needs to be super-class, base-class1, base-class2 and so on, + * so we reverse class hierarchy + */ + Collections.reverse(clist); + for (ClassSymbol cd : clist) { + for (Symbol i : cd.getEnclosedElements()) { + // consider only final, static and fields with ConstantExpressions + if (isFinal(i) && i.isStatic() && i.kind == VAR) { + VarSymbol v = (VarSymbol) i; + if (v.getConstantValue() != null) { + Pair p = new Pair<>(sym, v); + printStaticDefines(out, p); + } + } } } } - - /** - * Including super class fields. - */ - List getAllFields(TypeElement subclazz) { - List fields = new ArrayList<>(); - TypeElement cd = null; - Stack s = new Stack<>(); - - cd = subclazz; - while (true) { - s.push(cd); - TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass())); - if (c == null) + static void printStaticDefines(PrintWriter out, Pair p) { + ClassSymbol cls = p.fst; + VarSymbol f = p.snd; + Object value = f.getConstantValue(); + String valueStr = null; + switch (f.asType().getKind()) { + case BOOLEAN: + valueStr = (((Boolean) value) ? "1L" : "0L"); break; - cd = c; + case BYTE: case SHORT: case INT: + valueStr = value.toString() + "L"; + break; + case LONG: + // Visual C++ supports the i64 suffix, not LL. + valueStr = value.toString() + ((isWindows) ? "i64" : "LL"); + break; + case CHAR: + Character ch = (Character) value; + valueStr = String.valueOf(((int) ch) & 0xffff) + "L"; + break; + case FLOAT: + // bug compatible + float fv = ((Float) value).floatValue(); + valueStr = (Float.isInfinite(fv)) + ? ((fv < 0) ? "-" : "") + "Inff" + : value.toString() + "f"; + break; + case DOUBLE: + // bug compatible + double d = ((Double) value).doubleValue(); + valueStr = (Double.isInfinite(d)) + ? ((d < 0) ? "-" : "") + "InfD" + : value.toString(); + break; + default: + valueStr = null; } - - while (!s.empty()) { - cd = s.pop(); - fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements())); + if (valueStr != null) { + out.print("#undef "); + String cname = encode(cls.getQualifiedName(), EncoderType.CLASS); + String fname = encode(f.getSimpleName(), EncoderType.FIELDSTUB); + out.println(cname + "_" + fname); + out.print("#define " + cname + "_"); + out.println(fname + " " + valueStr); } - - return fields; } - - protected String defineForStatic(TypeElement c, VariableElement f) { - CharSequence cnamedoc = c.getQualifiedName(); - CharSequence fnamedoc = f.getSimpleName(); - - String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS); - String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB); - - Assert.check(f.getModifiers().contains(Modifier.STATIC)); - - if (f.getModifiers().contains(Modifier.FINAL)) { - Object value = null; - - value = f.getConstantValue(); - - if (value != null) { /* so it is a ConstantExpression */ - String constString = null; - if ((value instanceof Integer) - || (value instanceof Byte) - || (value instanceof Short)) { - /* covers byte, short, int */ - constString = value.toString() + "L"; - } else if (value instanceof Boolean) { - constString = ((Boolean) value) ? "1L" : "0L"; - } else if (value instanceof Character) { - Character ch = (Character) value; - constString = String.valueOf(((int) ch) & 0xffff) + "L"; - } else if (value instanceof Long) { - // Visual C++ supports the i64 suffix, not LL. - if (isWindows) - constString = value.toString() + "i64"; - else - constString = value.toString() + "LL"; - } else if (value instanceof Float) { - /* bug for bug */ - float fv = ((Float)value).floatValue(); - if (Float.isInfinite(fv)) - constString = ((fv < 0) ? "-" : "") + "Inff"; - else - constString = value.toString() + "f"; - } else if (value instanceof Double) { - /* bug for bug */ - double d = ((Double)value).doubleValue(); - if (Double.isInfinite(d)) - constString = ((d < 0) ? "-" : "") + "InfD"; - else - constString = value.toString(); - } - - if (constString != null) { - StringBuilder s = new StringBuilder("#undef "); - s.append(cname); s.append("_"); s.append(fname); s.append(lineSep); - s.append("#define "); s.append(cname); s.append("_"); - s.append(fname); s.append(" "); s.append(constString); - return s.toString(); - } - - } - } - - return null; - } - - - protected void writeMethods(Writer out, ClassSymbol sym, String cname) + protected void writeMethods(PrintWriter out, ClassSymbol sym, String cname) throws IOException, TypeSignature.SignatureException { - List classmethods = ElementFilter.methodsIn(sym.getEnclosedElements()); - for (ExecutableElement md: classmethods) { - if(md.getModifiers().contains(Modifier.NATIVE)){ - TypeMirror mtr = types.erasure(md.getReturnType()); - String sig = signature(md); - TypeSignature newtypesig = new TypeSignature(elements); + List classmethods = sym.getEnclosedElements(); + for (Symbol md : classmethods) { + if (isNative(md)) { + TypeSignature newtypesig = new TypeSignature(types); CharSequence methodName = md.getSimpleName(); - boolean longName = false; - for (ExecutableElement md2: classmethods) { + boolean isOverloaded = false; + for (Symbol md2 : classmethods) { if ((md2 != md) - && (methodName.equals(md2.getSimpleName())) - && (md2.getModifiers().contains(Modifier.NATIVE))) - longName = true; - + && (methodName.equals(md2.getSimpleName())) + && isNative(md2)) { + isOverloaded = true; + } } - println(out, "/*"); - println(out, " * Class: " + cname); - println(out, " * Method: " + - mangler.mangle(methodName, Mangle.Type.FIELDSTUB)); - println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr)); - println(out, " */"); - println(out, "JNIEXPORT " + jniType(mtr) + - " JNICALL " + - mangler.mangleMethod(md, sym, - (longName) ? - Mangle.Type.METHOD_JNI_LONG : - Mangle.Type.METHOD_JNI_SHORT)); - print(out, " (JNIEnv *, "); - List paramargs = md.getParameters(); - List args = new ArrayList<>(); - for (VariableElement p: paramargs) { - args.add(types.erasure(p.asType())); + out.println("/*"); + out.println(" * Class: " + cname); + out.println(" * Method: " + encode(methodName, EncoderType.FIELDSTUB)); + out.println(" * Signature: " + newtypesig.getSignature(md.type)); + out.println(" */"); + out.println("JNIEXPORT " + jniType(types.erasure(md.type.getReturnType())) + + " JNICALL " + encodeMethod(md, sym, isOverloaded)); + out.print(" (JNIEnv *, "); + out.print((md.isStatic()) + ? "jclass" + : "jobject"); + for (Type arg : types.erasure(md.type.getParameterTypes())) { + out.print(", "); + out.print(jniType(arg)); } - if (md.getModifiers().contains(Modifier.STATIC)) - print(out, "jclass"); - else - print(out, "jobject"); - - for (TypeMirror arg: args) { - print(out, ", "); - print(out, jniType(arg)); - } - println(out, ");" - + lineSep); + out.println(");"); + out.println(); } } } - - // c.f. MethodDoc.signature - String signature(ExecutableElement e) { - StringBuilder sb = new StringBuilder("("); - String sep = ""; - for (VariableElement p: e.getParameters()) { - sb.append(sep); - sb.append(types.erasure(p.asType()).toString()); - sep = ","; - } - sb.append(")"); - return sb.toString(); - } - - protected final String jniType(TypeMirror t) { - TypeElement throwable = elements.getTypeElement("java.lang.Throwable"); - TypeElement jClass = elements.getTypeElement("java.lang.Class"); - TypeElement jString = elements.getTypeElement("java.lang.String"); - Element tclassDoc = types.asElement(t); - - + @SuppressWarnings("fallthrough") + protected final String jniType(Type t) { switch (t.getKind()) { case ARRAY: { - TypeMirror ct = ((ArrayType) t).getComponentType(); + Type ct = ((Type.ArrayType)t).getComponentType(); switch (ct.getKind()) { case BOOLEAN: return "jbooleanArray"; case BYTE: return "jbyteArray"; @@ -420,16 +343,16 @@ public class JNIWriter { case LONG: return "jlong"; case FLOAT: return "jfloat"; case DOUBLE: return "jdouble"; - case DECLARED: { - if (tclassDoc.equals(jString)) + if (t.tsym.type == syms.stringType) { return "jstring"; - else if (types.isAssignable(t, throwable.asType())) + } else if (types.isAssignable(t, syms.throwableType)) { return "jthrowable"; - else if (types.isAssignable(t, jClass.asType())) + } else if (types.isAssignable(t, syms.classType)) { return "jclass"; - else + } else { return "jobject"; + } } } @@ -437,193 +360,145 @@ public class JNIWriter { return null; /* dead code. */ } - protected String fileTop() { - return "/* DO NOT EDIT THIS FILE - it is machine generated */"; + protected void fileTop(PrintWriter out) { + out.println("/* DO NOT EDIT THIS FILE - it is machine generated */"); } - protected String includes() { - return "#include "; + protected void includes(PrintWriter out) { + out.println("#include "); } /* * Deal with the C pre-processor. */ - protected String cppGuardBegin() { - return "#ifdef __cplusplus" + lineSep - + "extern \"C\" {" + lineSep - + "#endif"; + protected void cppGuardBegin(PrintWriter out) { + out.println("#ifdef __cplusplus"); + out.println("extern \"C\" {"); + out.println("#endif"); } - protected String cppGuardEnd() { - return "#ifdef __cplusplus" + lineSep - + "}" + lineSep - + "#endif"; + protected void cppGuardEnd(PrintWriter out) { + out.println("#ifdef __cplusplus"); + out.println("}"); + out.println("#endif"); } - protected String guardBegin(String cname) { - return "/* Header for class " + cname + " */" + lineSep - + lineSep - + "#ifndef _Included_" + cname + lineSep - + "#define _Included_" + cname; + protected void guardBegin(PrintWriter out, String cname) { + out.println("/* Header for class " + cname + " */"); + out.println(); + out.println("#ifndef _Included_" + cname); + out.println("#define _Included_" + cname); } - protected String guardEnd(String cname) { - return "#endif"; + protected void guardEnd(PrintWriter out) { + out.println("#endif"); } - protected void print(Writer out, String text) throws IOException { - out.write(text); - } - - protected void println(Writer out, String text) throws IOException { - out.write(text); - out.write(lineSep); - } - - - private static class Mangle { - - public static class Type { - public static final int CLASS = 1; - public static final int FIELDSTUB = 2; - public static final int FIELD = 3; - public static final int JNI = 4; - public static final int SIGNATURE = 5; - public static final int METHOD_JDK_1 = 6; - public static final int METHOD_JNI_SHORT = 7; - public static final int METHOD_JNI_LONG = 8; + String encodeMethod(Symbol msym, ClassSymbol clazz, + boolean isOverloaded) throws TypeSignature.SignatureException { + StringBuilder result = new StringBuilder(100); + result.append("Java_"); + /* JNI */ + result.append(encode(clazz.flatname.toString(), EncoderType.JNI)); + result.append('_'); + result.append(encode(msym.getSimpleName(), EncoderType.JNI)); + if (isOverloaded) { + TypeSignature typeSig = new TypeSignature(types); + StringBuilder sig = typeSig.getParameterSignature(msym.type); + result.append("__").append(encode(sig, EncoderType.JNI)); } + return result.toString(); + } - private Elements elems; - private Types types; + static enum EncoderType { + CLASS, + FIELDSTUB, + FIELD, + JNI, + SIGNATURE + } + @SuppressWarnings("fallthrough") + static String encode(CharSequence name, EncoderType mtype) { + StringBuilder result = new StringBuilder(100); + int length = name.length(); - Mangle(Elements elems, Types types) { - this.elems = elems; - this.types = types; - } - - public final String mangle(CharSequence name, int mtype) { - StringBuilder result = new StringBuilder(100); - int length = name.length(); - - for (int i = 0; i < length; i++) { - char ch = name.charAt(i); - if (isalnum(ch)) { - result.append(ch); - } else if ((ch == '.') && - mtype == Mangle.Type.CLASS) { - result.append('_'); - } else if (( ch == '$') && - mtype == Mangle.Type.CLASS) { - result.append('_'); - result.append('_'); - } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) { - result.append('_'); - } else if (ch == '_' && mtype == Mangle.Type.CLASS) { - result.append('_'); - } else if (mtype == Mangle.Type.JNI) { - String esc = null; - if (ch == '_') - esc = "_1"; - else if (ch == '.') - esc = "_"; - else if (ch == ';') - esc = "_2"; - else if (ch == '[') - esc = "_3"; - if (esc != null) { - result.append(esc); - } else { - result.append(mangleChar(ch)); + for (int i = 0; i < length; i++) { + char ch = name.charAt(i); + if (isalnum(ch)) { + result.append(ch); + continue; + } + switch (mtype) { + case CLASS: + switch (ch) { + case '.': + case '_': + result.append("_"); + break; + case '$': + result.append("__"); + break; + default: + result.append(encodeChar(ch)); } - } else if (mtype == Mangle.Type.SIGNATURE) { - if (isprint(ch)) { - result.append(ch); - } else { - result.append(mangleChar(ch)); + break; + case JNI: + switch (ch) { + case '/': + case '.': + result.append("_"); + break; + case '_': + result.append("_1"); + break; + case ';': + result.append("_2"); + break; + case '[': + result.append("_3"); + break; + default: + result.append(encodeChar(ch)); } - } else { - result.append(mangleChar(ch)); - } + break; + case SIGNATURE: + result.append(isprint(ch) ? ch : encodeChar(ch)); + break; + case FIELDSTUB: + result.append(ch == '_' ? ch : encodeChar(ch)); + break; + default: + result.append(encodeChar(ch)); } - - return result.toString(); } + return result.toString(); + } - public String mangleMethod(ExecutableElement method, TypeElement clazz, - int mtype) throws TypeSignature.SignatureException { - StringBuilder result = new StringBuilder(100); - result.append("Java_"); - - if (mtype == Mangle.Type.METHOD_JDK_1) { - result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS)); - result.append('_'); - result.append(mangle(method.getSimpleName(), - Mangle.Type.FIELD)); - result.append("_stub"); - return result.toString(); - } - - /* JNI */ - result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI)); - result.append('_'); - result.append(mangle(method.getSimpleName(), - Mangle.Type.JNI)); - if (mtype == Mangle.Type.METHOD_JNI_LONG) { - result.append("__"); - String typesig = signature(method); - TypeSignature newTypeSig = new TypeSignature(elems); - String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType()); - sig = sig.substring(1); - sig = sig.substring(0, sig.lastIndexOf(')')); - sig = sig.replace('/', '.'); - result.append(mangle(sig, Mangle.Type.JNI)); - } - - return result.toString(); + static String encodeChar(char ch) { + String s = Integer.toHexString(ch); + int nzeros = 5 - s.length(); + char[] result = new char[6]; + result[0] = '_'; + for (int i = 1; i <= nzeros; i++) { + result[i] = '0'; } - //where - private String getInnerQualifiedName(TypeElement clazz) { - return elems.getBinaryName(clazz).toString(); - } - - public final String mangleChar(char ch) { - String s = Integer.toHexString(ch); - int nzeros = 5 - s.length(); - char[] result = new char[6]; - result[0] = '_'; - for (int i = 1; i <= nzeros; i++) - result[i] = '0'; - for (int i = nzeros+1, j = 0; i < 6; i++, j++) - result[i] = s.charAt(j); - return new String(result); + for (int i = nzeros + 1, j = 0; i < 6; i++, j++) { + result[i] = s.charAt(j); } + return new String(result); + } - // Warning: duplicated in Gen - private String signature(ExecutableElement e) { - StringBuilder sb = new StringBuilder(); - String sep = "("; - for (VariableElement p: e.getParameters()) { - sb.append(sep); - sb.append(types.erasure(p.asType()).toString()); - sep = ","; - } - sb.append(")"); - return sb.toString(); - } - - /* Warning: Intentional ASCII operation. */ - private static boolean isalnum(char ch) { - return ch <= 0x7f && /* quick test */ - ((ch >= 'A' && ch <= 'Z') || - (ch >= 'a' && ch <= 'z') || + /* Warning: Intentional ASCII operation. */ + private static boolean isalnum(char ch) { + return ch <= 0x7f && /* quick test */ + ((ch >= 'A' && ch <= 'Z') || + (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')); - } + } - /* Warning: Intentional ASCII operation. */ - private static boolean isprint(char ch) { - return ch >= 32 && ch <= 126; - } + /* Warning: Intentional ASCII operation. */ + private static boolean isprint(char ch) { + return ch >= 32 && ch <= 126; } private static class TypeSignature { @@ -634,10 +509,10 @@ public class JNIWriter { } } - Elements elems; + JavacElements elems; + Types types; /* Signature Characters */ - private static final String SIG_VOID = "V"; private static final String SIG_BOOLEAN = "Z"; private static final String SIG_BYTE = "B"; @@ -650,209 +525,162 @@ public class JNIWriter { private static final String SIG_ARRAY = "["; private static final String SIG_CLASS = "L"; - - - public TypeSignature(Elements elems){ - this.elems = elems; + public TypeSignature(Types types) { + this.types = types; } - /* - * Returns the type signature of a field according to JVM specs - */ - public String getTypeSignature(String javasignature) throws SignatureException { - return getParamJVMSignature(javasignature); - } - - /* - * Returns the type signature of a method according to JVM specs - */ - public String getTypeSignature(String javasignature, TypeMirror returnType) + StringBuilder getParameterSignature(Type mType) throws SignatureException { - String signature = null; //Java type signature. - String typeSignature = null; //Internal type signature. - List params = new ArrayList<>(); //List of parameters. - String paramsig = null; //Java parameter signature. - String paramJVMSig = null; //Internal parameter signature. - String returnSig = null; //Java return type signature. - String returnJVMType = null; //Internal return type signature. - int dimensions = 0; //Array dimension. - - int startIndex = -1; - int endIndex = -1; - StringTokenizer st = null; - int i = 0; - - // Gets the actual java signature without parentheses. - if (javasignature != null) { - startIndex = javasignature.indexOf("("); - endIndex = javasignature.indexOf(")"); + StringBuilder result = new StringBuilder(); + for (Type pType : mType.getParameterTypes()) { + result.append(getJvmSignature(pType)); } + return result; + } - if (((startIndex != -1) && (endIndex != -1)) - &&(startIndex+1 < javasignature.length()) - &&(endIndex < javasignature.length())) { - signature = javasignature.substring(startIndex+1, endIndex); - } + StringBuilder getReturnSignature(Type mType) + throws SignatureException { + return getJvmSignature(mType.getReturnType()); + } - // Separates parameters. - if (signature != null) { - if (signature.contains(",")) { - st = new StringTokenizer(signature, ","); - if (st != null) { - while (st.hasMoreTokens()) { - params.add(st.nextToken()); - } - } - } else { - params.add(signature); - } - } - - /* JVM type signature. */ - typeSignature = "("; - - // Gets indivisual internal parameter signature. - while (params.isEmpty() != true) { - paramsig = params.remove(i).trim(); - paramJVMSig = getParamJVMSignature(paramsig); - if (paramJVMSig != null) { - typeSignature += paramJVMSig; - } - } - - typeSignature += ")"; - - // Get internal return type signature. - - returnJVMType = ""; - if (returnType != null) { - dimensions = dimensions(returnType); - } - - //Gets array dimension of return type. - while (dimensions-- > 0) { - returnJVMType += "["; - } - if (returnType != null) { - returnSig = qualifiedTypeName(returnType); - returnJVMType += getComponentType(returnSig); - } else { - System.out.println("Invalid return type."); - } - - typeSignature += returnJVMType; - - return typeSignature; + StringBuilder getSignature(Type mType) throws SignatureException { + StringBuilder sb = new StringBuilder(); + sb.append("(").append(getParameterSignature(mType)).append(")"); + sb.append(getReturnSignature(mType)); + return sb; } /* - * Returns internal signature of a parameter. + * Returns jvm internal signature. */ - private String getParamJVMSignature(String paramsig) throws SignatureException { - String paramJVMSig = ""; - String componentType =""; + static class JvmTypeVisitor extends JNIWriter.SimpleTypeVisitor { - if(paramsig != null){ - - if(paramsig.contains("[]")) { - // Gets array dimension. - int endindex = paramsig.indexOf("[]"); - componentType = paramsig.substring(0, endindex); - String dimensionString = paramsig.substring(endindex); - if(dimensionString != null){ - while(dimensionString.contains("[]")){ - paramJVMSig += "["; - int beginindex = dimensionString.indexOf("]") + 1; - if(beginindex < dimensionString.length()){ - dimensionString = dimensionString.substring(beginindex); - }else - dimensionString = ""; - } - } - } else componentType = paramsig; - - paramJVMSig += getComponentType(componentType); + @Override + public Type visitClassType(Type.ClassType t, StringBuilder s) { + setDeclaredType(t, s); + return null; } - return paramJVMSig; - } - /* - * Returns internal signature of a component. - */ - private String getComponentType(String componentType) throws SignatureException { + @Override + public Type visitArrayType(Type.ArrayType t, StringBuilder s) { + s.append("["); + return t.getComponentType().accept(this, s); + } - String JVMSig = ""; - - if(componentType != null){ - switch (componentType) { - case "void": JVMSig += SIG_VOID; break; - case "boolean": JVMSig += SIG_BOOLEAN; break; - case "byte": JVMSig += SIG_BYTE; break; - case "char": JVMSig += SIG_CHAR; break; - case "short": JVMSig += SIG_SHORT; break; - case "int": JVMSig += SIG_INT; break; - case "long": JVMSig += SIG_LONG; break; - case "float": JVMSig += SIG_FLOAT; break; - case "double": JVMSig += SIG_DOUBLE; break; + @Override + public Type visitType(Type t, StringBuilder s) { + if (t.isPrimitiveOrVoid()) { + s.append(getJvmPrimitiveSignature(t)); + return null; + } + return t.accept(this, s); + } + private void setDeclaredType(Type t, StringBuilder s) { + String classname = t.tsym.getQualifiedName().toString(); + classname = classname.replace('.', '/'); + s.append("L").append(classname).append(";"); + } + private String getJvmPrimitiveSignature(Type t) { + switch (t.getKind()) { + case VOID: return SIG_VOID; + case BOOLEAN: return SIG_BOOLEAN; + case BYTE: return SIG_BYTE; + case CHAR: return SIG_CHAR; + case SHORT: return SIG_SHORT; + case INT: return SIG_INT; + case LONG: return SIG_LONG; + case FLOAT: return SIG_FLOAT; + case DOUBLE: return SIG_DOUBLE; default: - if (!componentType.equals("")) { - TypeElement classNameDoc = elems.getTypeElement(componentType); - - if (classNameDoc == null) { - throw new SignatureException(componentType); - } - else { - String classname = classNameDoc.getQualifiedName().toString(); - String newclassname = classname.replace('.', '/'); - JVMSig += "L"; - JVMSig += newclassname; - JVMSig += ";"; - } - } - break; + Assert.error("unknown type: should not happen"); } + return null; } - return JVMSig; } - int dimensions(TypeMirror t) { - if (t.getKind() != TypeKind.ARRAY) - return 0; - return 1 + dimensions(((ArrayType) t).getComponentType()); - } - - - String qualifiedTypeName(TypeMirror type) { - TypeVisitor v = new SimpleTypeVisitor8() { - @Override - public Name visitArray(ArrayType t, Void p) { - return t.getComponentType().accept(this, p); - } - - @Override - public Name visitDeclared(DeclaredType t, Void p) { - return ((TypeElement) t.asElement()).getQualifiedName(); - } - - @Override - public Name visitPrimitive(PrimitiveType t, Void p) { - return elems.getName(t.toString()); - } - - @Override - public Name visitNoType(NoType t, Void p) { - if (t.getKind() == TypeKind.VOID) - return elems.getName("void"); - return defaultAction(t, p); - } - - @Override - public Name visitTypeVariable(TypeVariable t, Void p) { - return t.getUpperBound().accept(this, p); - } - }; - return v.visit(type).toString(); + StringBuilder getJvmSignature(Type type) { + Type t = types.erasure(type); + StringBuilder sig = new StringBuilder(); + JvmTypeVisitor jv = new JvmTypeVisitor(); + jv.visitType(t, sig); + return sig; } } + static class SimpleTypeVisitor implements Type.Visitor { + + protected final R DEFAULT_VALUE; + + protected SimpleTypeVisitor() { + DEFAULT_VALUE = null; + } + + protected SimpleTypeVisitor(R defaultValue) { + DEFAULT_VALUE = defaultValue; + } + + protected R defaultAction(Type t, P p) { + return DEFAULT_VALUE; + } + + @Override + public R visitClassType(Type.ClassType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitWildcardType(Type.WildcardType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitArrayType(Type.ArrayType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitMethodType(Type.MethodType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitPackageType(Type.PackageType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitTypeVar(Type.TypeVar t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitCapturedType(Type.CapturedType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitForAll(Type.ForAll t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitUndetVar(Type.UndetVar t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitErrorType(Type.ErrorType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitAnnotatedType(Type.AnnotatedType t, P p) { + return defaultAction(t, p); + } + + @Override + public R visitType(Type t, P p) { + return defaultAction(t, p); + } + } } diff --git a/langtools/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java b/langtools/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java index a4a9ab6c5ec..9513e4a9721 100644 --- a/langtools/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java +++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7150368 8003412 8000407 + * @bug 7150368 8003412 8000407 8031545 * @summary javac should include basic ability to generate native headers */ diff --git a/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java b/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java index 93b21aeb789..6cdcd109da3 100644 --- a/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java +++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,50 +129,52 @@ public class TestClass1 { native List[] gaamn(); // overloaded Java methods - byte bm1() { return 0; } - short sm1() { return 0; } - int im1() { return 0; } - long lm1() { return 0; } - float fm1() { return 0; } - double dm1() { return 0; } - Object om1() { return null; } - String tm1() { return ""; } - List gm1() { return null; } - void vm1() { } + byte bmo() { return 0; } + short smo() { return 0; } + int imo() { return 0; } + long lmo() { return 0; } + float fmo() { return 0; } + double dmo() { return 0; } + Object omo() { return null; } + String tmo() { return ""; } + List gmo() { return null; } + void vmo() { } - byte bm2(int i) { return 0; } - short sm2(int i) { return 0; } - int im2(int i) { return 0; } - long lm2(int i) { return 0; } - float fm2(int i) { return 0; } - double dm2(int i) { return 0; } - Object om2(int i) { return null; } - String tm2(int i) { return ""; } - List gm2(int i) { return null; } - void vm2(int i) { } + byte bmo(int i) { return 0; } + short smo(int i) { return 0; } + int imo(int i) { return 0; } + long lmo(int i) { return 0; } + float fmo(int i) { return 0; } + double dmo(int i) { return 0; } + Object omo(int i) { return null; } + String tmo(int i) { return ""; } + List gmo(int i) { return null; } + void vmo(int i) { } // overloaded native methods - native byte bmn1(); - native short smn1(); - native int imn1(); - native long lmn1(); - native float fmn1(); - native double dmn1(); - native Object omn1(); - native String tmn1(); - native List gmn1(); - native void vmn1(); + native byte bmno(); + native short smno(); + native int imno(); + native long lmno(); + native float fmno(); + native double dmno(); + native Object omno(); + native String tmno(); + native List gmno(); + native void vmno(); + native Inner1 icmno(); - native byte bmn2(int i); - native short smn2(int i); - native int imn2(int i); - native long lmn2(int i); - native float fmn2(int i); - native double dmn2(int i); - native Object omn2(int i); - native String tmn2(int i); - native List gmn2(int i); - native void vmn2(int i); + native byte bmno(int i); + native short smno(int i); + native int imno(int i); + native long lmno(int i); + native float fmno(int i); + native double dmno(int i); + native Object omno(int i); + native String tmno(int i); + native List gmno(int i); + native void vmno(int i); + native Inner1 icmno(Inner1 in1); // arg types for Java methods void mb(byte b) { } @@ -266,50 +268,50 @@ public class TestClass1 { native void vmn(); // overloaded Java methods - byte bm1() { return 0; } - short sm1() { return 0; } - int im1() { return 0; } - long lm1() { return 0; } - float fm1() { return 0; } - double dm1() { return 0; } - Object om1() { return null; } - String tm1() { return ""; } - List gm1() { return null; } - void vm1() { } + byte bmo() { return 0; } + short smo() { return 0; } + int imo() { return 0; } + long lmo() { return 0; } + float fmo() { return 0; } + double dmo() { return 0; } + Object omo() { return null; } + String tmo() { return ""; } + List gmo() { return null; } + void vmo() { } - byte bm2(int i) { return 0; } - short sm2(int i) { return 0; } - int im2(int i) { return 0; } - long lm2(int i) { return 0; } - float fm2(int i) { return 0; } - double dm2(int i) { return 0; } - Object om2(int i) { return null; } - String tm2(int i) { return ""; } - List gm2(int i) { return null; } - void vm2(int i) { } + byte bmo(int i) { return 0; } + short smo(int i) { return 0; } + int imo(int i) { return 0; } + long lmo(int i) { return 0; } + float fmo(int i) { return 0; } + double dmo(int i) { return 0; } + Object omo(int i) { return null; } + String tmo(int i) { return ""; } + List gmo(int i) { return null; } + void vmo(int i) { } // overloaded native methods - native byte bmn1(); - native short smn1(); - native int imn1(); - native long lmn1(); - native float fmn1(); - native double dmn1(); - native Object omn1(); - native String tmn1(); - native List gmn1(); - native void vmn1(); + native byte bmno(); + native short smno(); + native int imno(); + native long lmno(); + native float fmno(); + native double dmno(); + native Object omno(); + native String tmno(); + native List gmno(); + native void vmno(); - native byte bmn2(int i); - native short smn2(int i); - native int imn2(int i); - native long lmn2(int i); - native float fmn2(int i); - native double dmn2(int i); - native Object omn2(int i); - native String tmn2(int i); - native List gmn2(int i); - native void vmn2(int i); + native byte bmno(int i); + native short smno(int i); + native int imno(int i); + native long lmno(int i); + native float fmno(int i); + native double dmno(int i); + native Object omno(int i); + native String tmno(int i); + native List gmno(int i); + native void vmno(int i); // arg types for Java methods void mb(byte b) { } From c704bce1fac8e707a17570bd4aa366906318dee7 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:44:29 -0800 Subject: [PATCH 094/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- langtools/THIRD_PARTY_README | 1312 ++++++++++++++++++++-------------- 1 file changed, 766 insertions(+), 546 deletions(-) diff --git a/langtools/THIRD_PARTY_README b/langtools/THIRD_PARTY_README index ee5463a922e..ba48858c28f 100644 --- a/langtools/THIRD_PARTY_README +++ b/langtools/THIRD_PARTY_README @@ -2,11 +2,12 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- %% This notice is provided with respect to ASM Bytecode Manipulation -Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2011 France Télécom All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,8 +41,41 @@ THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -%% This notice is provided with respect to CodeViewer 1.0, which is included -with JDK 7. +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. --- begin of LICENSE --- @@ -81,8 +115,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ------------------------------------------------------------------------------- -%% This notice is provided with respect to Cryptix AES 3.2.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -121,7 +155,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to CUP Parser Generator for -Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -148,7 +182,7 @@ performance of this software. ------------------------------------------------------------------------------- %% This notice is provided with respect to Document Object Model (DOM) Level 2 -& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -212,19 +246,52 @@ site-policy@w3.org. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Elliptic Curve Cryptography, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. You are receiving a copy of the Elliptic Curve Cryptography library in source -form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 -runtime. +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. -The terms of the Oracle license do NOT apply to the Elliptic Curve -Cryptography library program; it is licensed under the following license, -separately from the Oracle programs you receive. If you do not wish to install -this program, you may delete the library named libsunec.so (on Solaris and -Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory -reserved for native libraries. --- begin of LICENSE --- @@ -735,13 +802,138 @@ That's all there is to it! ------------------------------------------------------------------------------- -%% This notice is provided with respect to FontConfig 2.5, which is -included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Dynalink library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Copyright (c) 2009-2013, Attila Szegedi + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- end of LICENSE --- + +%% This notice is provided with respect to Joni library which is included +with the Nashorn technology. + +--- begin of LICENSE --- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on Linux and Solaris. --- begin of LICENSE --- -Copyright ¬© 2001,2003 Keith Packard +Copyright © 2001,2003 Keith Packard Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the @@ -765,7 +957,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to IAIK PKCS#11 Wrapper, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -816,7 +1008,7 @@ POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- %% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which -is included with JRE 7, JDK 7, and OpenJDK 7. +may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -852,8 +1044,8 @@ their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to IJG JPEG 6b, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -891,8 +1083,35 @@ assumed by the product vendor. -------------------------------------------------------------------------------- -%% This notice is provided with respect to JOpt-Simple v3.0, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -921,8 +1140,39 @@ included with JRE 7, JDK 7, and OpenJDK 7. -------------------------------------------------------------------------------- +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Kerberos functionality, which -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -934,7 +1184,7 @@ which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- %% This notice is provided with respect to Kerberos functionality from -FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -967,8 +1217,8 @@ FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Kronos OpenGL headers, which is -included with JDK 7 and OpenJDK 7 source distributions. +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1000,8 +1250,8 @@ included with JDK 7 and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- -%% This notice is provided with respect to libpng 1.2.18, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1014,8 +1264,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -1112,14 +1364,14 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -May 15, 2007 +July 7, 2011 --- end of LICENSE --- ------------------------------------------------------------------------------- -%% This notice is provided with respect to libungif 4.1.3, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1147,8 +1399,8 @@ THE SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Little CMS 2.0, which is -included with OpenJDK 7. +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. --- begin of LICENSE --- @@ -1183,7 +1435,7 @@ U.S. and other countries. ------------------------------------------------------------------------------- %% This notice is provided with respect to Mesa 3D Graphics Library v4.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. --- begin of LICENSE --- @@ -1213,8 +1465,402 @@ which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -1257,8 +1903,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% This notice is provided with respect to Relax NG Object/Parser v.20050510, -which is included with JRE 7, JDK 7, and OpenJDK 7. +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1285,8 +1953,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to RelaxNGCC v1.12, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1335,487 +2003,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Mozilla Rhino v1.7R3, which -is included with JRE 7, JDK 7, and OpenJDK 7 - ---- begin of LICENSE --- - - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A - Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] - ---- end of LICENSE --- - -------------------------------------------------------------------------------- - -%% This notice is provided with respect to SAX 2.0.1, which is included -with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1876,8 +2065,8 @@ with JRE 7, JDK 7, and OpenJDK 7. ------------------------------------------------------------------------------- -%% This notice is provided with respect to SoftFloat version 2b, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. --- begin of LICENSE --- @@ -1909,12 +2098,41 @@ satisfied. ------------------------------------------------------------------------------- +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + %% Portions licensed from Taligent, Inc. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Thai Dictionary, which is -included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1947,8 +2165,8 @@ SOFTWARE. ------------------------------------------------------------------------------- -%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR -v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- @@ -1959,7 +2177,7 @@ Privacy Policy. For trademark usage, see the Unicode® Consortium Name and Trademark Usage Policy. A. Unicode Copyright. - 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. 2. Certain documents and files on this website contain a legend indicating that "Modification is permitted." Any person is hereby authorized, @@ -2094,7 +2312,7 @@ SOFTWARE. COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -2134,8 +2352,8 @@ the property of their respective owners. ------------------------------------------------------------------------------- -%% This notice is provided with respect to UPX v3.01, which is included -with JRE 7 on Windows. +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. --- begin of LICENSE --- @@ -2274,7 +2492,7 @@ The UPX license file is at http://upx.sourceforge.net/upx-license.html. ------------------------------------------------------------------------------- %% This notice is provided with respect to Xfree86-VidMode Extension 1.0, -which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -2326,8 +2544,8 @@ to do so,subject to the following conditions: ------------------------------------------------------------------------------- -%% This notice is provided with respect to X Window System 6.8.2, which is -included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. --- begin of LICENSE --- @@ -3131,12 +3349,12 @@ info@urwpp.de or design@bigelowandholmes.com ------------------------------------------------------------------------------- -%% This notice is provided with respect to zlib v1.2.3, which is included -with JRE 7, JDK 7, and OpenJDK 7 +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- - version 1.2.3, July 18th, 2005 + version 1.2.5, July 18th, 2005 Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler @@ -3163,16 +3381,18 @@ with JRE 7, JDK 7, and OpenJDK 7 ------------------------------------------------------------------------------- -%% This notice is provided with respect to the following which is -included with JRE 7, JDK 7, and OpenJDK 7, except where noted: +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: - Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] Apache Jakarta BCEL 5.2 Apache Jakarta Regexp 1.4 - Apache Santuario XMLSec-Java 1.4.2 + Apache Santuario XML Security for Java 1.5.4 Apache Xalan-Java 2.7.1 - Apache Xerces2 Java 2.10.0 + Apache Xerces Java 2.10.0 Apache XML Resolver 1.1 + Dynalink 0.5 --- begin of LICENSE --- From 3dd998447a102a32c2131f98f6919b4179c9a166 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 6 Feb 2014 17:44:37 +0530 Subject: [PATCH 095/265] 8033763: Add tests to assert map identity of certain objects Reviewed-by: hannesw, lagergren --- nashorn/make/build.xml | 5 ++ nashorn/make/project.properties | 5 +- .../script/currently-failing/gettersetter.js | 48 +++++++++++++++ nashorn/test/script/maptests/builtins.js | 58 +++++++++++++++++++ nashorn/test/script/maptests/constructor.js | 36 ++++++++++++ nashorn/test/script/maptests/maputil.js | 38 ++++++++++++ nashorn/test/script/maptests/object_create.js | 40 +++++++++++++ .../test/script/maptests/object_literals.js | 46 +++++++++++++++ nashorn/test/script/maptests/point.js | 49 ++++++++++++++++ nashorn/test/script/maptests/property_add.js | 46 +++++++++++++++ .../test/script/maptests/property_delete.js | 48 +++++++++++++++ nashorn/test/script/maptests/proto.js | 56 ++++++++++++++++++ 12 files changed, 473 insertions(+), 2 deletions(-) create mode 100644 nashorn/test/script/currently-failing/gettersetter.js create mode 100644 nashorn/test/script/maptests/builtins.js create mode 100644 nashorn/test/script/maptests/constructor.js create mode 100644 nashorn/test/script/maptests/maputil.js create mode 100644 nashorn/test/script/maptests/object_create.js create mode 100644 nashorn/test/script/maptests/object_literals.js create mode 100644 nashorn/test/script/maptests/point.js create mode 100644 nashorn/test/script/maptests/property_add.js create mode 100644 nashorn/test/script/maptests/property_delete.js create mode 100644 nashorn/test/script/maptests/proto.js diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 93342248de5..78a713bfc46 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -282,6 +282,11 @@ grant codeBase "file:/${basedir}/test/script/trusted/*" { permission java.security.AllPermission; }; +grant codeBase "file:/${basedir}/test/script/maptests/*" { + permission java.io.FilePermission "${basedir}/test/script/maptests/*","read"; + permission java.lang.RuntimePermission "nashorn.debugMode"; +}; + grant codeBase "file:/${basedir}/test/script/basic/*" { permission java.io.FilePermission "${basedir}/test/script/-", "read"; permission java.io.FilePermission "$${user.dir}", "read"; diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index ad36744836b..d51e72e4180 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -115,6 +115,7 @@ run.classpath=\ test.dir=test test.script.dir=test/script test.basic.dir=test/script/basic +test.maptests.dir=test/script/maptests test.error.dir=test/script/error test.sandbox.dir=test/script/sandbox test.trusted.dir=test/script/trusted @@ -125,7 +126,7 @@ testjfx.dir=${test.script.dir}/jfx testmarkdown.dir=${test.script.dir}/markdown test-sys-prop.test.dir=${test.dir} -test-sys-prop.test.js.roots=${test.basic.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir} +test-sys-prop.test.js.roots=${test.basic.dir} ${test.maptests.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir} test-sys-prop.test262.suite.dir=${test262.suite.dir} test-sys-prop.es5conform.testcases.dir=${test.external.dir}/ES5Conform/TestCases test-sys-prop.test.basic.dir=${test.basic.dir} @@ -278,7 +279,7 @@ run.test.jvmargs.octane.main=${run.test.jvmargs.common} run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy # VM options for script tests with @fork option -test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} +test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath} # path of rhino.jar for benchmarks rhino.jar= diff --git a/nashorn/test/script/currently-failing/gettersetter.js b/nashorn/test/script/currently-failing/gettersetter.js new file mode 100644 index 00000000000..88f6949233c --- /dev/null +++ b/nashorn/test/script/currently-failing/gettersetter.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +function Foo() { + return { + get foo() { return 42; }, + set foo(x) {} + } +} + +var obj1 = Foo(); +var obj2 = Foo(); + +assertSameMap(obj1, obj2, "Object literals before change"); + +Object.defineProperty(obj2, "foo", { get: function() { return 'hello' } }); +assertSameMap(obj1, obj2); + +Object.defineProperty(obj2, "foo", { set: function(x) { print(x) } }); +assertSameMap(obj1, obj2); diff --git a/nashorn/test/script/maptests/builtins.js b/nashorn/test/script/maptests/builtins.js new file mode 100644 index 00000000000..4de2ec9a8da --- /dev/null +++ b/nashorn/test/script/maptests/builtins.js @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +// check that builtin objects share property map + +assertSameMap(new Boolean(true), new Boolean(false)); +assertSameMap(new Number(3), new Number(Math.PI)); +assertSameMap(new String('hello'), new String('world')); +assertSameMap(new Object(), new Object()); +assertSameMap(/hello/, /world/); +// try w/without regexp flags +assertSameMap(/hello/i, /world/g); +assertSameMap(new Date(), new Date()); +assertSameMap(new Date(2000, 1, 1), new Date(1972, 5, 6)); +assertSameMap(Function(), Function()); +assertSameMap(Function("x", "return x"), Function("x", "return x*x")); +assertSameMap(new Error(), new Error()); +assertSameMap(new Error('foo'), new Error('bar')); +assertSameMap(new EvalError(), new EvalError()); +assertSameMap(new EvalError('foo'), new EvalError('bar')); +assertSameMap(new RangeError(), new RangeError()); +assertSameMap(new RangeError('foo'), new RangeError('bar')); +assertSameMap(new ReferenceError(), new ReferenceError()); +assertSameMap(new ReferenceError('foo'), new ReferenceError('bar')); +assertSameMap(new SyntaxError(), new SyntaxError()); +assertSameMap(new SyntaxError('foo'), new SyntaxError('bar')); +assertSameMap(new TypeError(), new TypeError()); +assertSameMap(new TypeError('foo'), new TypeError('bar')); +assertSameMap(new URIError(), new URIError()); +assertSameMap(new URIError('foo'), new URIError('bar')); diff --git a/nashorn/test/script/maptests/constructor.js b/nashorn/test/script/maptests/constructor.js new file mode 100644 index 00000000000..5722a3c15b9 --- /dev/null +++ b/nashorn/test/script/maptests/constructor.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "point.js"); + +// use constructor defined in a different script file +// These objects should share the map +assertSameMap(new Point(2, 3), new Point(43, 23)); +assertSameMap(new Point(), new Point()); +assertSameMap(new Point(), new Point(3, 1)); diff --git a/nashorn/test/script/maptests/maputil.js b/nashorn/test/script/maptests/maputil.js new file mode 100644 index 00000000000..aa85d7f1220 --- /dev/null +++ b/nashorn/test/script/maptests/maputil.js @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @subtest + */ + +function assertSameMap(obj1, obj2, msg) { + if (! Debug.identical(Debug.map(obj1), Debug.map(obj2))) { + fail(obj1.constructor + " instances don't share map"); + } +} + +function assertNotSameMap(obj1, obj2, msg) { + if (Debug.identical(Debug.map(obj1), Debug.map(obj2))) { + fail(obj1.constructor + " and " + obj2.constructor + " instances share map"); + } +} diff --git a/nashorn/test/script/maptests/object_create.js b/nashorn/test/script/maptests/object_create.js new file mode 100644 index 00000000000..1b1bd604c85 --- /dev/null +++ b/nashorn/test/script/maptests/object_create.js @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +// Objects created by Object.create +var obj1 = Object.create(Object.prototype); +var obj2 = Object.create(Object.prototype); +assertSameMap(obj1, obj2); + +var proto = { foo: 233 }; +obj1 = Object.create(proto); +obj2 = Object.create(proto); +assertSameMap(obj1, obj2); diff --git a/nashorn/test/script/maptests/object_literals.js b/nashorn/test/script/maptests/object_literals.js new file mode 100644 index 00000000000..c73d80140c7 --- /dev/null +++ b/nashorn/test/script/maptests/object_literals.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +// Object literals created at the same callsite +function makeObject() { + return { foo: 34 } +} +assertSameMap(makeObject(), makeObject()); + +function makeObject2() { + return { foo: 42, bar: 'hello' } +} +assertSameMap(makeObject2(), makeObject2()); + +// Object literals created at different callsites +assertSameMap({}, {}); +assertSameMap({foo: 4}, {foo: 'hello'}); +assertSameMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54}); diff --git a/nashorn/test/script/maptests/point.js b/nashorn/test/script/maptests/point.js new file mode 100644 index 00000000000..38b8fa2513a --- /dev/null +++ b/nashorn/test/script/maptests/point.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/** + * @subtest + */ + +function Point(x, y) { + this.x =x; this.y =y; +} + +Point.prototype.toString = function() { + return "(" + this.x + "," + this.y + ")"; +} + +Point.prototype.modulus = function() { + return Math.sqrt(this.x*this.x + this.y*this.y); +} + +Point.prototype.argument = function() { + return Math.atan2(this.y, this.x); +} + +load(__DIR__ + "maputil.js"); + +assertSameMap(new Point(2, 3), new Point(43, 23)); +assertSameMap(new Point(), new Point()); +assertSameMap(new Point(), new Point(3, 1)); diff --git a/nashorn/test/script/maptests/property_add.js b/nashorn/test/script/maptests/property_add.js new file mode 100644 index 00000000000..2026455459d --- /dev/null +++ b/nashorn/test/script/maptests/property_add.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +function Foo() {} + +var obj1 = new Foo(); +var obj2 = new Foo(); + +assertSameMap(obj1, obj2); + +// property addition at same callsite +function addX(obj, val) { + obj.x = val; +} +addX(obj1, 3); +addX(obj2, 'hello'); + +assertSameMap(obj1, obj2); diff --git a/nashorn/test/script/maptests/property_delete.js b/nashorn/test/script/maptests/property_delete.js new file mode 100644 index 00000000000..e2824dd6315 --- /dev/null +++ b/nashorn/test/script/maptests/property_delete.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +function Foo() { + this.x = 33; +} + +var obj1 = new Foo(); +var obj2 = new Foo(); + +assertSameMap(obj1, obj2); + +// property deletion at same callsite +function deleteX(obj) { + delete obj.x; +} +deleteX(obj1); +deleteX(obj2); + +assertSameMap(obj1, obj2); diff --git a/nashorn/test/script/maptests/proto.js b/nashorn/test/script/maptests/proto.js new file mode 100644 index 00000000000..afb59509a0a --- /dev/null +++ b/nashorn/test/script/maptests/proto.js @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @option -Dnashorn.debug=true + * @fork + */ + +load(__DIR__ + "maputil.js"); + +// add/delete property to proto (direct/indirect) should +// not affect the property map of the objects + +var proto2 = { foo: 334 } +var proto = Object.create(proto2); +proto.bar = "hello"; + +var obj1 = Object.create(proto); +var obj2 = Object.create(proto); + +assertSameMap(obj1, obj2); + +proto.newX = 'world'; +assertSameMap(obj1, obj2); + +delete proto.newX; +assertSameMap(obj1, obj2); + +proto2.newX = "foo"; +assertSameMap(obj1, obj2); + +delete proto2.newX; +assertSameMap(obj1, obj2); + + From 118cf2ba60204d7870f5d4e42d3623670ede714a Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Fri, 7 Feb 2014 18:47:46 +0530 Subject: [PATCH 096/265] 8033924: Default permissions are not given for eval code Reviewed-by: lagergren, jlaskey --- .../jdk/nashorn/internal/runtime/Context.java | 2 +- .../internal/runtime/ScriptLoader.java | 5 +- nashorn/test/script/sandbox/safeprops.js | 65 +++++++++++++++++++ .../api/scripting/ScriptEngineTest.java | 41 ++++++++++++ 4 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 nashorn/test/script/sandbox/safeprops.js diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk/nashorn/internal/runtime/Context.java index e15ddd2c8fb..3e6a1488fa3 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java @@ -956,7 +956,7 @@ public final class Context { final URL url = source.getURL(); final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader; - final CodeSource cs = url == null ? null : new CodeSource(url, (CodeSigner[])null); + final CodeSource cs = new CodeSource(url, (CodeSigner[])null); final CodeInstaller installer = new ContextCodeInstaller(this, loader, cs); final Compiler compiler = new Compiler(installer, strict); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java index 78185b1c416..52c98d40734 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java @@ -70,9 +70,8 @@ final class ScriptLoader extends NashornLoader { * @return Installed class. */ synchronized Class installClass(final String name, final byte[] data, final CodeSource cs) { - if (cs == null) { - return defineClass(name, data, 0, data.length, new ProtectionDomain(null, getPermissions(null))); - } + // null check + cs.getClass(); return defineClass(name, data, 0, data.length, cs); } } diff --git a/nashorn/test/script/sandbox/safeprops.js b/nashorn/test/script/sandbox/safeprops.js new file mode 100644 index 00000000000..dc12e74f9be --- /dev/null +++ b/nashorn/test/script/sandbox/safeprops.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Try to access System properties safe to read for any code. + * No security exception expected. + * + * @test + * @security + * @run + * @bug 8033924: Default permissions are not given for eval code + */ + +var propNames = [ + "java.version", + "java.vendor", + "java.vendor.url", + "java.class.version", + "os.name", + "os.version", + "os.arch", + "file.separator", + "path.separator", + "line.separator", + "java.specification.version", + "java.specification.vendor", + "java.specification.name", + "java.vm.specification.version", + "java.vm.specification.vendor", + "java.vm.specification.name", + "java.vm.version", + "java.vm.vendor", + "java.vm.name" +]; + +// no security exception expected +for (var p in propNames) { + java.lang.System.getProperty(propNames[p]); +} + +// no security exception expected +for (var p in propNames) { + var name = propNames[p]; + eval('java.lang.System.getProperty(name)'); +} diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java index df8696d8e4c..5219914519f 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java @@ -560,6 +560,47 @@ public class ScriptEngineTest { assertTrue(reached[0]); } + // properties that can be read by any code + private static String[] propNames = { + "java.version", + "java.vendor", + "java.vendor.url", + "java.class.version", + "os.name", + "os.version", + "os.arch", + "file.separator", + "path.separator", + "line.separator", + "java.specification.version", + "java.specification.vendor", + "java.specification.name", + "java.vm.specification.version", + "java.vm.specification.vendor", + "java.vm.specification.name", + "java.vm.version", + "java.vm.vendor", + "java.vm.name" + }; + + // @bug 8033924: Default permissions are not given for eval code + @Test + public void checkPropertyReadPermissions() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + + for (final String name : propNames) { + checkProperty(e, name); + } + } + + private static void checkProperty(final ScriptEngine e, final String name) + throws ScriptException { + String value = System.getProperty(name); + e.put("name", name); + assertEquals(value, e.eval("java.lang.System.getProperty(name)")); + } + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); // Returns String that would be the result of calling PrintWriter.println From 615623c47378996b7750496be2c2e1190c92d245 Mon Sep 17 00:00:00 2001 From: Matherey Nunez Date: Tue, 11 Feb 2014 12:05:22 +0100 Subject: [PATCH 097/265] 8033231: test fails with java.lang.UnsatisfiedLinkError Reviewed-by: attila, sundar --- nashorn/test/script/basic/JDK-8026161.js | 6 ++-- .../test/script/basic/JDK-8026161.js.EXPECTED | 4 +-- .../models/IntFloatOverloadSelection.java | 36 +++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java diff --git a/nashorn/test/script/basic/JDK-8026161.js b/nashorn/test/script/basic/JDK-8026161.js index 49f888b71ee..e3e88486402 100644 --- a/nashorn/test/script/basic/JDK-8026161.js +++ b/nashorn/test/script/basic/JDK-8026161.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,5 +28,5 @@ * @run */ -print(new java.awt.Color(1, 1, 1)) // creates Color[r=1,g=1,b=1] -print(new java.awt.Color(1.0, 1.0, 1.0)) // Color[r=255,g=255,b=255] +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1)) +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1.0)) diff --git a/nashorn/test/script/basic/JDK-8026161.js.EXPECTED b/nashorn/test/script/basic/JDK-8026161.js.EXPECTED index c7b00b083f1..ac032cff452 100644 --- a/nashorn/test/script/basic/JDK-8026161.js.EXPECTED +++ b/nashorn/test/script/basic/JDK-8026161.js.EXPECTED @@ -1,2 +1,2 @@ -java.awt.Color[r=1,g=1,b=1] -java.awt.Color[r=255,g=255,b=255] +int +float diff --git a/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java b/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java new file mode 100644 index 00000000000..947896b362a --- /dev/null +++ b/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.nashorn.test.models; + +public class IntFloatOverloadSelection { + + public static String overloadedMethod(int i) { + return "int"; + } + + public static String overloadedMethod(float f) { + return "float"; + } +} From 1dd97ac6e73d22ba62e2070006886fedfae7c747 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Fri, 14 Feb 2014 19:02:02 +0530 Subject: [PATCH 098/265] 8011964: need indexed access to externally-managed ByteBuffer Reviewed-by: lagergren, hannesw --- .../api/scripting/ScriptObjectMirror.java | 18 ++ .../internal/objects/NativeObject.java | 23 ++ .../internal/runtime/arrays/ArrayData.java | 11 + .../runtime/arrays/ByteBufferArrayData.java | 203 ++++++++++++++++++ .../runtime/resources/Messages.properties | 1 + nashorn/test/script/basic/JDK-8011964.js | 60 ++++++ .../test/script/basic/JDK-8011964.js.EXPECTED | 20 ++ .../api/scripting/ScriptObjectMirrorTest.java | 24 +++ 8 files changed, 360 insertions(+) create mode 100644 nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java create mode 100644 nashorn/test/script/basic/JDK-8011964.js create mode 100644 nashorn/test/script/basic/JDK-8011964.js.EXPECTED diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java index 01f72c0008f..7a9792df19c 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -25,6 +25,7 @@ package jdk.nashorn.api.scripting; +import java.nio.ByteBuffer; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permissions; @@ -41,6 +42,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import javax.script.Bindings; +import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.GlobalObject; @@ -259,6 +261,22 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin }); } + /** + * Nashorn extension: setIndexedPropertiesToExternalArrayData. + * set indexed properties be exposed from a given nio ByteBuffer. + * + * @param buf external buffer - should be a nio ByteBuffer + */ + public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) { + inGlobal(new Callable() { + @Override public Void call() { + sobj.setArray(ArrayData.allocate(buf)); + return null; + } + }); + } + + @Override public boolean isInstance(final Object obj) { if (! (obj instanceof ScriptObjectMirror)) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java index d102c0fb011..26335f631e8 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java @@ -31,6 +31,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -58,6 +59,7 @@ import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; import jdk.nashorn.internal.runtime.linker.NashornBeansLinker; @@ -100,6 +102,27 @@ public final class NativeObject { return typeError("not.an.object", ScriptRuntime.safeToString(obj)); } + /** + * Nashorn extension: setIndexedPropertiesToExternalArrayData + * + * @param self self reference + * @param obj object whose index properties are backed by buffer + * @param buf external buffer - should be a nio ByteBuffer + * @return the 'obj' object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) + public static Object setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) { + Global.checkObject(obj); + final ScriptObject sobj = (ScriptObject)obj; + if (buf instanceof ByteBuffer) { + sobj.setArray(ArrayData.allocate((ByteBuffer)buf)); + } else { + throw typeError("not.a.bytebuffer", "setIndexedPropertiesToExternalArrayData's buf argument"); + } + return sobj; + } + + /** * ECMA 15.2.3.2 Object.getPrototypeOf ( O ) * diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java index 5c0c0476bfa..0aa1d9ebfcc 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.runtime.arrays; import java.lang.invoke.MethodHandle; +import java.nio.ByteBuffer; import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyDescriptor; @@ -143,6 +144,16 @@ public abstract class ArrayData { return new ObjectArrayData(array, array.length); } + /** + * Allocate an ArrayData wrapping a given nio ByteBuffer + * + * @param buf the nio ByteBuffer to wrap + * @return the ArrayData + */ + public static ArrayData allocate(final ByteBuffer buf) { + return new ByteBufferArrayData((ByteBuffer)buf); + } + /** * Apply a freeze filter to an ArrayData. * diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java new file mode 100644 index 00000000000..58ea1318f53 --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.nashorn.internal.runtime.arrays; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +import java.nio.ByteBuffer; +import jdk.nashorn.internal.runtime.GlobalObject; +import jdk.nashorn.internal.runtime.PropertyDescriptor; +import jdk.nashorn.internal.runtime.ScriptRuntime; + +/** + * Implementation of {@link ArrayData} that wraps a nio ByteBuffer + */ +final class ByteBufferArrayData extends ArrayData { + private final ByteBuffer buf; + + ByteBufferArrayData(final int length) { + super(length); + this.buf = ByteBuffer.allocateDirect(length); + } + + /** + * Constructor + * + * @param buf ByteBuffer to create array data with. + */ + ByteBufferArrayData(final ByteBuffer buf) { + super(buf.capacity()); + this.buf = buf; + } + + /** + * Returns property descriptor for element at a given index + * + * @param global the global object + * @param index the index + * + * @return property descriptor for element + */ + public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) { + // make the index properties not configurable + return global.newDataDescriptor(getObject(index), false, true, true); + } + + @Override + public ArrayData copy() { + throw unsupported("copy"); + } + + @Override + public Object[] asObjectArray() { + throw unsupported("asObjectArray"); + } + + @Override + public void setLength(final long length) { + throw new UnsupportedOperationException("setLength"); + } + + @Override + public void shiftLeft(int by) { + throw unsupported("shiftLeft"); + } + + @Override + public ArrayData shiftRight(int by) { + throw unsupported("shiftRight"); + } + + @Override + public ArrayData ensure(long safeIndex) { + if (safeIndex < buf.capacity()) { + return this; + } + + throw unsupported("ensure"); + } + + @Override + public ArrayData shrink(long newLength) { + throw unsupported("shrink"); + } + + @Override + public ArrayData set(int index, Object value, boolean strict) { + if (value instanceof Number) { + buf.put(index, ((Number)value).byteValue()); + return this; + } + + throw typeError("not.a.number", ScriptRuntime.safeToString(value)); + } + + @Override + public ArrayData set(int index, int value, boolean strict) { + buf.put(index, (byte)value); + return this; + } + + @Override + public ArrayData set(int index, long value, boolean strict) { + buf.put(index, (byte)value); + return this; + } + + @Override + public ArrayData set(int index, double value, boolean strict) { + buf.put(index, (byte)value); + return this; + } + + @Override + public int getInt(int index) { + return 0x0ff & buf.get(index); + } + + @Override + public long getLong(int index) { + return 0x0ff & buf.get(index); + } + + @Override + public double getDouble(int index) { + return 0x0ff & buf.get(index); + } + + @Override + public Object getObject(int index) { + return (int)(0x0ff & buf.get(index)); + } + + @Override + public boolean has(int index) { + return index > -1 && index < buf.capacity(); + } + + @Override + public boolean canDelete(final int index, final boolean strict) { + return false; + } + + @Override + public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) { + return false; + } + + @Override + public ArrayData delete(int index) { + throw unsupported("delete"); + } + + @Override + public ArrayData delete(long fromIndex, long toIndex) { + throw unsupported("delete"); + } + + @Override + public ArrayData push(final boolean strict, final Object... items) { + throw unsupported("push"); + } + + @Override + public Object pop() { + throw unsupported("pop"); + } + + @Override + public ArrayData slice(long from, long to) { + throw unsupported("slice"); + } + + @Override + public ArrayData convert(final Class type) { + throw unsupported("convert"); + } + + private UnsupportedOperationException unsupported(final String method) { + return new UnsupportedOperationException(method); + } +} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties index 95993c9f40e..e1c4d1f1f8a 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -78,6 +78,7 @@ type.error.not.a.string={0} is not a String type.error.not.a.function={0} is not a function type.error.not.a.constructor={0} is not a constructor function type.error.not.a.file={0} is not a File +type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer # operations not permitted on undefined type.error.cant.call.undefined=Cannot call undefined diff --git a/nashorn/test/script/basic/JDK-8011964.js b/nashorn/test/script/basic/JDK-8011964.js new file mode 100644 index 00000000000..a46023ebb6f --- /dev/null +++ b/nashorn/test/script/basic/JDK-8011964.js @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8011964: need indexed access to externally-managed ByteBuffer + * + * @test + * @run + */ + + +var ByteBuffer = Java.type("java.nio.ByteBuffer"); +var buf = ByteBuffer.allocate(5); + +var obj = {} +Object.setIndexedPropertiesToExternalArrayData(obj, buf); + +obj[0] = 'A'.charCodeAt(0); +obj[1] = 'B'.charCodeAt(0); +obj[2] = 'C'.charCodeAt(0); +obj[3] = 'D'.charCodeAt(0); +obj[4] = 'E'.charCodeAt(0); + +for (var i = 0; i < buf.capacity(); i++) { + print("obj[" + i + "] = " + obj[i]); + print("buf.get(" + i + ") = " + buf.get(i)); +} + +var arr = []; +Object.setIndexedPropertiesToExternalArrayData(arr, buf); +obj[0] = 'a'.charCodeAt(0); +obj[1] = 'b'.charCodeAt(0); +obj[2] = 'c'.charCodeAt(0); +obj[3] = 'd'.charCodeAt(0); +obj[4] = 'e'.charCodeAt(0); + +for (var i in arr) { + print("arr[" + i + "] = " + arr[i]); + print("buf.get(" + i + ") = " + buf.get(i)); +} diff --git a/nashorn/test/script/basic/JDK-8011964.js.EXPECTED b/nashorn/test/script/basic/JDK-8011964.js.EXPECTED new file mode 100644 index 00000000000..5bec2bdfeac --- /dev/null +++ b/nashorn/test/script/basic/JDK-8011964.js.EXPECTED @@ -0,0 +1,20 @@ +obj[0] = 65 +buf.get(0) = 65 +obj[1] = 66 +buf.get(1) = 66 +obj[2] = 67 +buf.get(2) = 67 +obj[3] = 68 +buf.get(3) = 68 +obj[4] = 69 +buf.get(4) = 69 +arr[0] = 97 +buf.get(0) = 97 +arr[1] = 98 +buf.get(1) = 98 +arr[2] = 99 +buf.get(2) = 99 +arr[3] = 100 +buf.get(3) = 100 +arr[4] = 101 +buf.get(4) = 101 diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java index 544f4ea7920..241f22c39ea 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java @@ -25,6 +25,7 @@ package jdk.nashorn.api.scripting; +import java.nio.ByteBuffer; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -229,6 +230,29 @@ public class ScriptObjectMirrorTest { assertTrue(newObj instanceof ScriptObjectMirror); } + @Test + public void indexPropertiesExternalBufferTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + final ScriptObjectMirror obj = (ScriptObjectMirror)e.eval("var obj = {}; obj"); + final ByteBuffer buf = ByteBuffer.allocate(5); + int i; + for (i = 0; i < 5; i++) { + buf.put(i, (byte)(i+10)); + } + obj.setIndexedPropertiesToExternalArrayData(buf); + + for (i = 0; i < 5; i++) { + assertEquals((byte)(i+10), ((Number)e.eval("obj[" + i + "]")).byteValue()); + } + + e.eval("for (i = 0; i < 5; i++) obj[i] = 0"); + for (i = 0; i < 5; i++) { + assertEquals((byte)0, ((Number)e.eval("obj[" + i + "]")).byteValue()); + assertEquals((byte)0, buf.get(i)); + } + } + @Test public void conversionTest() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); From 073ec486706fda5f2b1023dc18d49687faf090a2 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Mon, 13 Jan 2014 14:45:02 -0800 Subject: [PATCH 099/265] 7129980: Third Party License Readme update for JDK8 Reviewed-by: lana, tbell --- nashorn/THIRD_PARTY_README | 3488 +++++++++++++++++++++++++++++++++++- 1 file changed, 3485 insertions(+), 3 deletions(-) diff --git a/nashorn/THIRD_PARTY_README b/nashorn/THIRD_PARTY_README index 02202a16573..ba48858c28f 100644 --- a/nashorn/THIRD_PARTY_README +++ b/nashorn/THIRD_PARTY_README @@ -1,11 +1,813 @@ DO NOT TRANSLATE OR LOCALIZE. ----------------------------- -%% This notice is provided with respect to ECMAScript Language -Specification ECMA-262 Edition 5.1 which is included with the Nashorn -technology. +%% This notice is provided with respect to ASM Bytecode Manipulation +Framework v5.0, which may be included with JRE 8, and JDK 8, and +OpenJDK 8. --- begin of LICENSE --- + +Copyright (c) 2000-2011 France Télécom +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to BSDiff v4.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which may be +included with JDK 8. + +--- begin of LICENSE --- + +Copyright 1999 by CoolServlets.com. + +Any errors or suggested improvements to this class can be reported as +instructed on CoolServlets.com. We hope you enjoy this program... your +comments will encourage further development! This software is distributed +under the terms of the BSD License. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +Neither name of CoolServlets.com nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY COOLSERVLETS.COM AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Cryptix AES 3.2.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Cryptix General License + +Copyright (c) 1995-2005 The Cryptix Foundation Limited. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND +CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CUP Parser Generator for +Java 0.10k, which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both the +copyright notice and this permission notice and warranty disclaimer appear in +supporting documentation, and that the names of the authors or their +employers not be used in advertising or publicity pertaining to distribution of +the software without specific, written prior permission. + +The authors and their employers disclaim all warranties with regard to +this software, including all implied warranties of merchantability and fitness. +In no event shall the authors or their employers be liable for any special, +indirect or consequential damages or any damages whatsoever resulting from +loss of use, data or profits, whether in an action of contract, negligence or +other tortious action, arising out of or in connection with the use or +performance of this software. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Document Object Model (DOM) Level 2 +& 3, which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +W3C SOFTWARE NOTICE AND LICENSE + +http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) +agree that you have read, understood, and will comply with the following terms +and conditions. + +Permission to copy, modify, and distribute this software and its +documentation, with or without modification, for any purpose and without fee +or royalty is hereby granted, provided that you include the following on ALL +copies of the software and documentation or portions thereof, including +modifications: + + 1.The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + + 2.Any pre-existing intellectual property disclaimers, notices, or terms and + conditions. If none exist, the W3C Software Short Notice should be included + (hypertext is preferred, text is permitted) within the body of any + redistributed or derivative code. + + 3.Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS +MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR +PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY +THIRD PARTY PATENTS,COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL +OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR +DOCUMENTATION. The name and trademarks of copyright holders may NOT be used +in advertising or publicity pertaining to the software without specific, +written prior permission. Title to copyright in this software and any +associated documentation will at all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 +2002. This version removes the copyright ownership notice such that this +license can be used with materials other than those owned by the W3C, reflects +that ERCIM is now a host of the W3C, includes references to this specific +dated version of the license, and removes the ambiguous grant of "use". +Otherwise, this version is the same as the previous version and is written so +as to preserve the Free Software Foundation's assessment of GPL compatibility +and OSI's certification under the Open Source Definition. Please see our +Copyright FAQ for common questions about using materials from our site, +including specific terms and conditions for packages like libwww, Amaya, and +Jigsaw. Other questions about this notice can be directed to +site-policy@w3.org. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Dynalink v0.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2009-2013, Attila Szegedi + +All rights reserved.Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following conditions are +met:* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. * Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. * Neither the name of Attila +Szegedi nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Elliptic Curve Cryptography, which +may be included with JRE 8, JDK 8, and OpenJDK 8. + +You are receiving a copy of the Elliptic Curve Cryptography library in source +form with the JDK 8 and OpenJDK 8 source distributions, and as object code in +the JRE 8 & JDK 8 runtimes. + +In the case of the JRE 8 & JDK 8 runtimes, the terms of the Oracle license do +NOT apply to the Elliptic Curve Cryptography library; it is licensed under the +following license, separately from Oracle's JDK & JRE. If you do not wish to +install the Elliptic Curve Cryptography library, you may delete the library +named libsunec.so (on Solaris and Linux systems) or sunec.dll (on Windows +systems) from the JRE bin directory reserved for native libraries. + + +--- begin of LICENSE --- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which may be included with +JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + Copyright notice Copyright © 2011 Ecma International Ecma International @@ -120,4 +922,2684 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + --- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which may be +included with JRE 8, JDK 8, and OpenJDK 8 source distributions on +Linux and Solaris. + +--- begin of LICENSE --- + +Copyright © 2001,2003 Keith Packard + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and that +the name of Keith Packard not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior permission. +Keith Packard makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL KEITH +PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IAIK PKCS#11 Wrapper, +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +IAIK PKCS#11 Wrapper License + +Copyright (c) 2002 Graz University of Technology. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by IAIK of Graz University of + Technology." + + Alternately, this acknowledgment may appear in the software itself, if and + wherever such third-party acknowledgments normally appear. + +4. The names "Graz University of Technology" and "IAIK of Graz University of + Technology" must not be used to endorse or promote products derived from this + software without prior written permission. + +5. Products derived from this software may not be called "IAIK PKCS Wrapper", + nor may "IAIK" appear in their name, without prior written permission of + Graz University of Technology. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +LICENSOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which +may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 1995-2010 International Business Machines Corporation and others + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +provided that the above copyright notice(s) and this permission notice appear +in all copies of the Software and that both the above copyright notice(s) and +this permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE +LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IJG JPEG 6b, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to Joni v1.1.9, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + Copyright (c) 2004-2009 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to JSON, which may be included +with JRE 8 & JDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality, which +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + (C) Copyright IBM Corp. 1999 All Rights Reserved. + Copyright 1997 The Open Group Research Institute. All rights reserved. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality from +FundsXpress, INC., which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may require + a specific license from the United States Government. It is the + responsibility of any person or organization contemplating export to + obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. FundsXpress makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kronos OpenGL headers, which may be +included with JDK 8 and OpenJDK 8 source distributions. + +--- begin of LICENSE --- + + Copyright (c) 2007 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), to + deal in the Materials without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Materials, and to permit persons to whom the Materials are + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Materials. + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE + MATERIALS. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions Copyright Eastman Kodak Company 1992 + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libpng 1.5.4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +July 7, 2011 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libungif 4.1.3, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Little CMS 2.4, which may be +included with OpenJDK 8. + +--- begin of LICENSE --- + +Little CMS +Copyright (c) 1998-2010 Marti Maria Saguer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Lucida is a registered trademark or trademark of Bigelow & Holmes in the +U.S. and other countries. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mesa 3D Graphics Library v4.1, +which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions. + +--- begin of LICENSE --- + + Mesa 3-D graphics library + Version: 4.1 + + Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mozilla Network Security +Services (NSS), which is supplied with the JDK test suite in the OpenJDK +source code repository. It is licensed under Mozilla Public License (MPL), +version 2.0. + +The NSS libraries are supplied in executable form, built from unmodified +NSS source code labeled with the "NSS_3.13.1_RTM" release tag. + +The NSS source code is available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/src + +The NSS libraries are available in the OpenJDK source code repository at: + jdk/test/sun/security/pkcs11/nss/lib + +--- begin of LICENSE --- + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + +Copyright (c) 1999-2004 David Corcoran +Copyright (c) 1999-2004 Ludovic Rousseau +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by: + David Corcoran + http://www.linuxnet.com (MUSCLE) +4. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +Changes to this license can be made only by the copyright author with +explicit written consent. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to PorterStemmer v4, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +See: http://tartarus.org/~martin/PorterStemmer + +The software is completely free for any purpose, unless notes at the head of +the program text indicates otherwise (which is rare). In any case, the notes +about licensing are never more restrictive than the BSD License. + +In every case where the software is not written by me (Martin Porter), this +licensing arrangement has been endorsed by the contributor, and it is +therefore unnecessary to ask the contributor again to confirm it. + +I have not asked any contributors (or their employers, if they have them) for +proofs that they have the right to distribute their software in this way. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Relax NG Object/Parser v.20050510, +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) Kohsuke Kawaguchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright +notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to RelaxNGCC v1.12, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (c) 2000-2003 Daisuke Okajima and Kohsuke Kawaguchi. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by Daisuke Okajima + and Kohsuke Kawaguchi (http://relaxngcc.sf.net/)." + +Alternately, this acknowledgment may appear in the software itself, if and +wherever such third-party acknowledgments normally appear. + +4. The names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission. For + written permission, please contact the copyright holders. + +5. Products derived from this software may not be called "RELAXNGCC", nor may + "RELAXNGCC" appear in their name, without prior written permission of the + copyright holders. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE APACHE +SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SAX 2.0.1, which may be included +with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + SAX is free! + + In fact, it's not possible to own a license to SAX, since it's been placed in + the public domain. + + No Warranty + + Because SAX is released to the public domain, there is no warranty for the + design or for the software implementation, to the extent permitted by + applicable law. Except when otherwise stated in writing the copyright holders + and/or other parties provide SAX "as is" without warranty of any kind, either + expressed or implied, including, but not limited to, the implied warranties + of merchantability and fitness for a particular purpose. The entire risk as + to the quality and performance of SAX is with you. Should SAX prove + defective, you assume the cost of all necessary servicing, repair or + correction. + + In no event unless required by applicable law or agreed to in writing will + any copyright holder, or any other party who may modify and/or redistribute + SAX, be liable to you for damages, including any general, special, incidental + or consequential damages arising out of the use or inability to use SAX + (including but not limited to loss of data or data being rendered inaccurate + or losses sustained by you or third parties or a failure of the SAX to + operate with any other programs), even if such holder or other party has been + advised of the possibility of such damages. + + Copyright Disclaimers + + This page includes statements to that effect by David Megginson, who would + have been able to claim copyright for the original work. SAX 1.0 + + Version 1.0 of the Simple API for XML (SAX), created collectively by the + membership of the XML-DEV mailing list, is hereby released into the public + domain. + + No one owns SAX: you may use it freely in both commercial and non-commercial + applications, bundle it with your software distribution, include it on a + CD-ROM, list the source code in a book, mirror the documentation at your own + web site, or use it in any other way you see fit. + + David Megginson, sax@megginson.com + 1998-05-11 + + SAX 2.0 + + I hereby abandon any property rights to SAX 2.0 (the Simple API for XML), and + release all of the SAX 2.0 source code, compiled code, and documentation + contained in this distribution into the Public Domain. SAX comes with NO + WARRANTY or guarantee of fitness for any purpose. + + David Megginson, david@megginson.com + 2000-05-05 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SoftFloat version 2b, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux/ARM. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + +SoftFloat was written by me, John R. Hauser. This work was made possible in +part by the International Computer Science Institute, located at Suite 600, +1947 Center Street, Berkeley, California 94704. Funding was partially +provided by the National Science Foundation under grant MIP-9311980. The +original version of this code was written as part of a project to build +a fixed-point vector processor in collaboration with the University of +California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL +LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO +FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER +SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, +COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE +SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, provided +that the minimal documentation requirements stated in the source code are +satisfied. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Sparkle 1.5, +which may be included with JRE 8 on Mac OS X. + +--- begin of LICENSE --- + +Copyright (c) 2012 Sparkle.org and Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions licensed from Taligent, Inc. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Thai Dictionary, which may be +included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Copyright (C) 1982 The Royal Institute, Thai Royal Government. + +Copyright (C) 1998 National Electronics and Computer Technology Center, +National Science and Technology Development Agency, +Ministry of Science Technology and Environment, +Thai Royal Government. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Unicode 6.2.0 & CLDR 21.0.1 +which may be included with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + +Unicode Terms of Use + +For the general privacy policy governing access to this site, see the Unicode +Privacy Policy. For trademark usage, see the Unicode® Consortium Name and +Trademark Usage Policy. + +A. Unicode Copyright. + 1. Copyright © 1991-2013 Unicode, Inc. All rights reserved. + + 2. Certain documents and files on this website contain a legend indicating + that "Modification is permitted." Any person is hereby authorized, + without fee, to modify such documents and files to create derivative + works conforming to the Unicode® Standard, subject to Terms and + Conditions herein. + + 3. Any person is hereby authorized, without fee, to view, use, reproduce, + and distribute all documents and files solely for informational + purposes in the creation of products supporting the Unicode Standard, + subject to the Terms and Conditions herein. + + 4. Further specifications of rights and restrictions pertaining to the use + of the particular set of data files known as the "Unicode Character + Database" can be found in Exhibit 1. + + 5. Each version of the Unicode Standard has further specifications of + rights and restrictions of use. For the book editions (Unicode 5.0 and + earlier), these are found on the back of the title page. The online + code charts carry specific restrictions. All other files, including + online documentation of the core specification for Unicode 6.0 and + later, are covered under these general Terms of Use. + + 6. No license is granted to "mirror" the Unicode website where a fee is + charged for access to the "mirror" site. + + 7. Modification is not permitted with respect to this document. All copies + of this document must be verbatim. + +B. Restricted Rights Legend. Any technical data or software which is licensed + to the United States of America, its agencies and/or instrumentalities + under this Agreement is commercial technical data or commercial computer + software developed exclusively at private expense as defined in FAR 2.101, + or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, + duplication, or disclosure by the Government is subject to restrictions as + set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov + 1995) and this Agreement. For Software, in accordance with FAR 12-212 or + DFARS 227-7202, as applicable, use, duplication or disclosure by the + Government is subject to the restrictions set forth in this Agreement. + +C. Warranties and Disclaimers. + 1. This publication and/or website may include technical or typographical + errors or other inaccuracies . Changes are periodically added to the + information herein; these changes will be incorporated in new editions + of the publication and/or website. Unicode may make improvements and/or + changes in the product(s) and/or program(s) described in this + publication and/or website at any time. + + 2. If this file has been purchased on magnetic or optical media from + Unicode, Inc. the sole and exclusive remedy for any claim will be + exchange of the defective media within ninety (90) days of original + purchase. + + 3. EXCEPT AS PROVIDED IN SECTION C.2, THIS PUBLICATION AND/OR SOFTWARE IS + PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, + OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + UNICODE AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR + OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH + ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. + +D. Waiver of Damages. In no event shall Unicode or its licensors be liable for + any special, incidental, indirect or consequential damages of any kind, or + any damages whatsoever, whether or not Unicode was advised of the + possibility of the damage, including, without limitation, those resulting + from the following: loss of use, data or profits, in connection with the + use, modification or distribution of this information or its derivatives. + +E.Trademarks & Logos. + 1. The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, + Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of + Unicode, Inc. Use of the information and materials found on this + website indicates your acknowledgement of Unicode, Inc.’s exclusive + worldwide rights in the Unicode Word Mark, the Unicode Logo, and the + Unicode trade names. + + 2. The Unicode Consortium Name and Trademark Usage Policy (“Trademark + Policy”) are incorporated herein by reference and you agree to abide by + the provisions of the Trademark Policy, which may be changed from time + to time in the sole discretion of Unicode, Inc. + + 3. All third party trademarks referenced herein are the property of their + respective owners. + +Miscellaneous. + 1. Jurisdiction and Venue. This server is operated from a location in the + State of California, United States of America. Unicode makes no + representation that the materials are appropriate for use in other + locations. If you access this server from other locations, you are + responsible for compliance with local laws. This Agreement, all use of + this site and any claims and damages resulting from use of this site are + governed solely by the laws of the State of California without regard to + any principles which would apply the laws of a different jurisdiction. + The user agrees that any disputes regarding this site shall be resolved + solely in the courts located in Santa Clara County, California. The user + agrees said courts have personal jurisdiction and agree to waive any + right to transfer the dispute to any other forum. + + 2. Modification by Unicode. Unicode shall have the right to modify this + Agreement at any time by posting it to this site. The user may not + assign any part of this Agreement without Unicode’s prior written + consent. + + 3. Taxes. The user agrees to pay any taxes arising from access to this + website or use of the information herein, except for those based on + Unicode’s net income. + + 4. Severability. If any provision of this Agreement is declared invalid or + unenforceable, the remaining provisions of this Agreement shall remain + in effect. + + 5. Entire Agreement. This Agreement constitutes the entire agreement + between the parties. + +EXHIBIT 1 +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +Unicode Data Files include all data files under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, and +http://www.unicode.org/cldr/data/. Unicode Data Files do not include PDF +online code charts under the directory http://www.unicode.org/Public/. +Software includes any source code published in the Unicode Standard or under +the directories http://www.unicode.org/Public/, +http://www.unicode.org/reports/, and http://www.unicode.org/cldr/data/. + +NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, +INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA +FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO +BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT +AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR +SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under the +Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the Unicode data files and any associated documentation (the "Data Files") +or Unicode software and any associated documentation (the "Software") to deal +in the Data Files or Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, and/or +sell copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that (a) the above +copyright notice(s) and this permission notice appear with all copies of the +Data Files or Software, (b) both the above copyright notice(s) and this +permission notice appear in associated documentation, and (c) there is clear +notice in each modified Data File or in the Software as well as in the +documentation associated with the Data File(s) or Software that the data or +software has been modified. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN +THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE +DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in these Data Files or Software without prior written authorization of the +copyright holder. + +Unicode and the Unicode logo are trademarks of Unicode, Inc. in the United +States and other countries. All third party trademarks referenced herein are +the property of their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to UPX v3.01, which may be included +with JRE 8 on Windows. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + + + ooooo ooo ooooooooo. ooooooo ooooo + `888' `8' `888 `Y88. `8888 d8' + 888 8 888 .d88' Y888..8P + 888 8 888ooo88P' `8888' + 888 8 888 .8PY888. + `88. .8' 888 d8' `888b + `YbodP' o888o o888o o88888o + + + The Ultimate Packer for eXecutables + Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar + http://wildsau.idv.uni-linz.ac.at/mfx/upx.html + http://www.nexus.hu/upx + http://upx.tsx.org + + +PLEASE CAREFULLY READ THIS LICENSE AGREEMENT, ESPECIALLY IF YOU PLAN +TO MODIFY THE UPX SOURCE CODE OR USE A MODIFIED UPX VERSION. + + +ABSTRACT +======== + + UPX and UCL are copyrighted software distributed under the terms + of the GNU General Public License (hereinafter the "GPL"). + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + As a special exception we grant the free usage of UPX for all + executables, including commercial programs. + See below for details and restrictions. + + +COPYRIGHT +========= + + UPX and UCL are copyrighted software. All rights remain with the authors. + + UPX is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + UPX is Copyright (C) 1996-2000 Laszlo Molnar + + UCL is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + + +GNU GENERAL PUBLIC LICENSE +========================== + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + UPX and UCL are distributed in the hope that they will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + + +SPECIAL EXCEPTION FOR COMPRESSED EXECUTABLES +============================================ + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + Hereby Markus F.X.J. Oberhumer and Laszlo Molnar grant you special + permission to freely use and distribute all UPX compressed programs + (including commercial ones), subject to the following restrictions: + + 1. You must compress your program with a completely unmodified UPX + version; either with our precompiled version, or (at your option) + with a self compiled version of the unmodified UPX sources as + distributed by us. + 2. This also implies that the UPX stub must be completely unmodfied, i.e. + the stub imbedded in your compressed program must be byte-identical + to the stub that is produced by the official unmodified UPX version. + 3. The decompressor and any other code from the stub must exclusively get + used by the unmodified UPX stub for decompressing your program at + program startup. No portion of the stub may get read, copied, + called or otherwise get used or accessed by your program. + + +ANNOTATIONS +=========== + + - You can use a modified UPX version or modified UPX stub only for + programs that are compatible with the GNU General Public License. + + - We grant you special permission to freely use and distribute all UPX + compressed programs. But any modification of the UPX stub (such as, + but not limited to, removing our copyright string or making your + program non-decompressible) will immediately revoke your right to + use and distribute a UPX compressed program. + + - UPX is not a software protection tool; by requiring that you use + the unmodified UPX version for your proprietary programs we + make sure that any user can decompress your program. This protects + both you and your users as nobody can hide malicious code - + any program that cannot be decompressed is highly suspicious + by definition. + + - You can integrate all or part of UPX and UCL into projects that + are compatible with the GNU GPL, but obviously you cannot grant + any special exceptions beyond the GPL for our code in your project. + + - We want to actively support manufacturers of virus scanners and + similar security software. Please contact us if you would like to + incorporate parts of UPX or UCL into such a product. + + + +Markus F.X.J. Oberhumer Laszlo Molnar +markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu + +Linz, Austria, 25 Feb 2000 + +Additional License(s) + +The UPX license file is at http://upx.sourceforge.net/upx-license.html. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Xfree86-VidMode Extension 1.0, +which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + +Version 1.1 of XFree86 ProjectLicence. + +Copyright (C) 1994-2004 The XFree86 Project, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicence, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so,subject to the following conditions: + + 1. Redistributions of source code must retain the above copyright + notice,this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution, and in the same place + and form as other copyright, license and disclaimer information. + + 3. The end-user documentation included with the redistribution, if any,must + include the following acknowledgment: "This product includes + software developed by The XFree86 Project, Inc (http://www.xfree86.org/) and + its contributors", in the same place and form as other third-party + acknowledgments. Alternately, this acknowledgment may appear in the software + itself, in the same form and location as other such third-party + acknowledgments. + + 4. Except as contained in this notice, the name of The XFree86 Project,Inc + shall not be used in advertising or otherwise to promote the sale, use + or other dealings in this Software without prior written authorization from + The XFree86 Project, Inc. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE XFREE86 PROJECT, INC OR ITS CONTRIBUTORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to X Window System 6.8.2, which may be +included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris. + +--- begin of LICENSE --- + + Licenses +The X.Org Foundation March 2004 + +1. Introduction + +The X.org Foundation X Window System distribution is a compilation of code and +documentation from many sources. This document is intended primarily as a +guide to the licenses used in the distribution: you must check each file +and/or package for precise redistribution terms. None-the-less, this summary +may be useful to many users. No software incorporating the XFree86 1.1 license +has been incorporated. + +This document is based on the compilation from XFree86. + +2. XFree86 License + +XFree86 code without an explicit copyright is covered by the following +copyright/license: + +Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the XFree86 Project shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the XFree86 Project. + +3. Other Licenses + +Portions of code are covered by the following licenses/copyrights. See +individual files for the copyright dates. + +3.1. X/MIT Copyrights + +3.1.1. X Consortium + +Copyright (C) X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X +CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from the X Consortium. + +X Window System is a trademark of X Consortium, Inc. + +3.1.2. The Open Group + +Copyright The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation. + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from The Open Group. 3.2. +Berkeley-based copyrights: + +o +3.2.1. General + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.2. UCB/LBL + +Copyright (c) 1993 The Regents of the University of California. All rights +reserved. + +This software was developed by the Computer Systems Engineering group at +Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and contributed to +Berkeley. + +All advertising materials mentioning features or use of this software must +display the following acknowledgement: This product includes software +developed by the University of California, Lawrence Berkeley Laboratory. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the University of California, Berkeley and its contributors. + + 4. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.2.3. The +NetBSD Foundation, Inc. + +Copyright (c) 2003 The NetBSD Foundation, Inc. All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation by Ben +Collver + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the NetBSD Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.2.4. Theodore +Ts'o. + +Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + and the entire permission notice in its entirety, including the disclaimer + of warranties. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. he name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE, ALL OF WHICH ARE HEREBY DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.5. Theo de Raadt and Damien Miller + +Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. Copyright (c) +2001-2002 Damien Miller. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.6. Todd C. Miller + +Copyright (c) 1998 Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3.2.7. Thomas +Winischhofer + +Copyright (C) 2001-2004 Thomas Winischhofer + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.3. NVIDIA Corp + +Copyright (c) 1996 NVIDIA, Corp. All rights reserved. + +NOTICE TO USER: The source code is copyrighted under U.S. and international +laws. NVIDIA, Corp. of Sunnyvale, California owns the copyright and as design +patents pending on the design and interface of the NV chips. Users and +possessors of this source code are hereby granted a nonexclusive, royalty-free +copyright and design patent license to use this code in individual and +commercial software. + +Any use of this source code must include, in the user documentation and +internal comments to the code, notices to the end user as follows: + +Copyright (c) 1996 NVIDIA, Corp. NVIDIA design patents pending in the U.S. and +foreign countries. + +NVIDIA, CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE +CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED +WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE +FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. 3.4. GLX Public +License + +GLX PUBLIC LICENSE (Version 1.0 (2/11/99)) ("License") + +Subject to any third party claims, Silicon Graphics, Inc. ("SGI") hereby +grants permission to Recipient (defined below), under Recipient's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below), and to permit persons to whom the Subject Software is +furnished in accordance with this License to do the same, subject to all of +the following terms and conditions, which Recipient accepts by engaging in any +such use, copying, modifying, merging, publishing, distributing, sublicensing +or selling: + +1. Definitions. + + (a) "Original Software" means source code of computer software code which + is described in Exhibit A as Original Software. + + (b) "Modifications" means any addition to or deletion from the substance + or structure of either the Original Software or any previous + Modifications. When Subject Software is released as a series of files, a + Modification means (i) any addition to or deletion from the contents of a + file containing Original Software or previous Modifications and (ii) any + new file that contains any part of the Original Code or previous + Modifications. + + (c) "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + (d) "Recipient" means an individual or a legal entity exercising rights + under, and complying with all of the terms of, this License. For legal + entities, "Recipient" includes any entity which controls, is controlled + by, or is under common control with Recipient. For purposes of this + definition, "control" of an entity means (a) the power, direct or + indirect, to direct or manage such entity, or (b) ownership of fifty + percent (50%) or more of the outstanding shares or beneficial ownership of + such entity. + +2. Redistribution of Source Code Subject to These Terms. Redistributions of +Subject Software in source code form must retain the notice set forth in +Exhibit A, below, in every file. A copy of this License must be included in +any documentation for such Subject Software where the recipients' rights +relating to Subject Software are described. Recipient may distribute the +source code version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 2 and Sections 3, 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the source code version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +3. Redistribution in Executable Form. The notice set forth in Exhibit A must +be conspicuously included in any notice in an executable version of Subject +Software, related documentation or collateral in which Recipient describes the +user's rights relating to the Subject Software. Recipient may distribute the +executable version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 3 and Sections 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the executable version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +4. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software which is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +5. No Trademark Rights. This License does not grant any rights to use any +trade name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from +the Subject Software without prior written permission of SGI. + +6. No Other Rights. This License does not grant any rights with respect to the +OpenGL API or to any software or hardware implementation thereof or to any +other software whatsoever, nor shall any other rights or licenses not +expressly granted hereunder arise by implication, estoppel or otherwise with +respect to the Subject Software. Title to and ownership of the Original +Software at all times remains with SGI. All rights in the Original Software +not expressly granted under this License are reserved. + +7. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +8. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Exhibit A notice required under Sections 2 and 3, +above, and in the text of any related documentation, license agreement or +collateral in which Recipient describes end user's rights relating to the +Subject Software. If Recipient obtains such knowledge after it makes Subject +Software available to any other person or entity, Recipient shall take other +steps (such as notifying appropriate mailing lists or newsgroups) reasonably +calculated to inform those who received the Subject Software that new +knowledge has been obtained. + +9. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON- INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY +CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK +STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER +COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF +THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY +TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SGI's NEGLIGENCE TO +THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO +THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO RECIPIENT. + +11. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold harmless Silicon Graphics, Inc. from +and against any loss, liability, damages, costs or expenses (including the +payment of reasonable attorneys fees) arising out of Recipient's use, +modification, reproduction and distribution of the Subject Software or out of +any representation or warranty made by Recipient. + +12. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +13. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed so as to achieve as nearly as +possible the same economic effect as the original provision and the remainder +of this License will remain in effect. This License shall be governed by and +construed in accordance with the laws of the United States and the State of +California as applied to agreements entered into and to be performed entirely +within California between California residents. Any litigation relating to +this License shall be subject to the exclusive jurisdiction of the Federal +Courts of the Northern District of California (or, absent subject matter +jurisdiction in such courts, the courts of the State of California), with +venue lying exclusively in Santa Clara County, California, with the losing +party responsible for costs, including without limitation, court costs and +reasonable attorneys fees and expenses. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. Any law or regulation which provides that the language of a contract +shall be construed against the drafter shall not apply to this License. + +Exhibit A + +The contents of this file are subject to Sections 2, 3, 4, 7, 8, 10, 12 and 13 +of the GLX Public License Version 1.0 (the "License"). You may not use this +file except in compliance with those sections of the License. You may obtain a +copy of the License at Silicon Graphics, Inc., attn: Legal Services, 2011 N. +Shoreline Blvd., Mountain View, CA 94043 or at +http://www.sgi.com/software/opensource/glx/license.html. + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON- +INFRINGEMENT. See the License for the specific language governing rights and +limitations under the License. + +The Original Software is GLX version 1.2 source code, released February, 1999. +The developer of the Original Software is Silicon Graphics, Inc. Those +portions of the Subject Software created by Silicon Graphics, Inc. are +Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. 3.5. CID +Font Code Public License + +CID FONT CODE PUBLIC LICENSE (Version 1.0 (3/31/99))("License") + +Subject to any applicable third party claims, Silicon Graphics, Inc. ("SGI") +hereby grants permission to Recipient (defined below), under SGI's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below) in both source code and executable form, and to permit persons +to whom the Subject Software is furnished in accordance with this License to +do the same, subject to all of the following terms and conditions, which +Recipient accepts by engaging in any such use, copying, modifying, merging, +publication, distributing, sublicensing or selling: + +1. Definitions. + + a. "Original Software" means source code of computer software code that is + described in Exhibit A as Original Software. + + b. "Modifications" means any addition to or deletion from the substance or + structure of either the Original Software or any previous Modifications. + When Subject Software is released as a series of files, a Modification + means (i) any addition to or deletion from the contents of a file + containing Original Software or previous Modifications and (ii) any new + file that contains any part of the Original Code or previous + Modifications. + + c. "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + d. "Recipient" means an individual or a legal entity exercising rights + under the terms of this License. For legal entities, "Recipient" includes + any entity that controls, is controlled by, or is under common control + with Recipient. For purposes of this definition, "control" of an entity + means (i) the power, direct or indirect, to direct or manage such entity, + or (ii) ownership of fifty percent (50%) or more of the outstanding shares + or beneficial ownership of such entity. + + e. "Required Notice" means the notice set forth in Exhibit A to this + License. + + f. "Accompanying Technology" means any software or other technology that + is not a Modification and that is distributed or made publicly available + by Recipient with the Subject Software. Separate software files that do + not contain any Original Software or any previous Modification shall not + be deemed a Modification, even if such software files are aggregated as + part of a product, or in any medium of storage, with any file that does + contain Original Software or any previous Modification. + +2. License Terms. All distribution of the Subject Software must be made +subject to the terms of this License. A copy of this License and the Required +Notice must be included in any documentation for Subject Software where +Recipient's rights relating to Subject Software and/or any Accompanying +Technology are described. Distributions of Subject Software in source code +form must also include the Required Notice in every file distributed. In +addition, a ReadMe file entitled "Important Legal Notice" must be distributed +with each distribution of one or more files that incorporate Subject Software. +That file must be included with distributions made in both source code and +executable form. A copy of the License and the Required Notice must be +included in that file. Recipient may distribute Accompanying Technology under +a license of Recipient's choice, which may contain terms different from this +License, provided that (i) Recipient is in compliance with the terms of this +License, (ii) such other license terms do not modify or supersede the terms of +this License as applicable to the Subject Software, (iii) Recipient hereby +indemnifies SGI for any liability incurred by SGI as a result of the +distribution of Accompanying Technology or the use of other license terms. + +3. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software that is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +4. Trademark Rights. This License does not grant any rights to use any trade +name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from or +incorporating any Subject Software without prior written permission of SGI. + +5. No Other Rights. No rights or licenses not expressly granted hereunder +shall arise by implication, estoppel or otherwise. Title to and ownership of +the Original Software at all times remains with SGI. All rights in the +Original Software not expressly granted under this License are reserved. + +6. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity, or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +7. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Required Notice, and in the text of any related +documentation, license agreement or collateral in which Recipient describes +end user's rights relating to the Subject Software. If Recipient obtains such +knowledge after it makes Subject Software available to any other person or +entity, Recipient shall take other steps (such as notifying appropriate +mailing lists or newsgroups) reasonably calculated to provide such knowledge +to those who received the Subject Software. + +8. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SUBJECT SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SUBJECT SOFTWARE. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO THIS EXCLUSION AND +LIMITATION MAY NOT APPLY TO RECIPIENT TO THE EXTENT SO DISALLOWED. + +10. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold SGI and its successors and assigns +harmless from and against any loss, liability, damages, costs or expenses +(including the payment of reasonable attorneys fees) arising out of +(Recipient's use, modification, reproduction and distribution of the Subject +Software or out of any representation or warranty made by Recipient. + +11. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +12. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable by any judicial or administrative authority having proper +jurisdiction with respect thereto, such provision shall be reformed so as to +achieve as nearly as possible the same economic effect as the original +provision and the remainder of this License will remain in effect. This +License shall be governed by and construed in accordance with the laws of the +United States and the State of California as applied to agreements entered +into and to be performed entirely within California between California +residents. Any litigation relating to this License shall be subject to the +exclusive jurisdiction of the Federal Courts of the Northern District of +California (or, absent subject matter jurisdiction in such courts, the courts +of the State of California), with venue lying exclusively in Santa Clara +County, California, with the losing party responsible for costs, including +without limitation, court costs and reasonable attorneys fees and expenses. +The application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. Any law or regulation that +provides that the language of a contract shall be construed against the +drafter shall not apply to this License. + +Exhibit A + +Copyright (c) 1994-1999 Silicon Graphics, Inc. + +The contents of this file are subject to the CID Font Code Public License +Version 1.0 (the "License"). You may not use this file except in compliance +with the License. You may obtain a copy of the License at Silicon Graphics, +Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +or at http://www.sgi.com/software/opensource/cid/license.html + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF +NON-INFRINGEMENT. See the License for the specific language governing rights +and limitations under the License. + +The Original Software (as defined in the License) is CID font code that was +developed by Silicon Graphics, Inc. Those portions of the Subject Software (as +defined in the License) that were created by Silicon Graphics, Inc. are +Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved. + +[NOTE: When using this text in connection with Subject Software delivered +solely in object code form, Recipient may replace the words "this file" with +"this software" in both the first and second sentences.] 3.6. Bitstream Vera +Fonts Copyright + +The fonts have a generous copyright, allowing derivative works (as long as +"Bitstream" or "Vera" are not in the names), and full redistribution (so long +as they are not *sold* by themselves). They can be be bundled, redistributed +and sold with any software. + +The fonts are distributed under the following copyright: + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a +trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated documentation +files (the "Font Software"), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit persons to +whom the Font Software is furnished to do so, subject to the following +conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular the +designs of glyphs or characters in the Fonts may be modified and additional +glyphs or characters may be added to the Fonts, only if the fonts are renamed +to names not containing either the words "Bitstream" or the word "Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream Vera" +names. + +The Font Software may be sold as part of a larger software package but no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO +USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the Gnome Foundation or Bitstream Inc., respectively. For +further information, contact: fonts at gnome dot org. 3.7. Bigelow & Holmes +Inc and URW++ GmbH Luxi font license + +Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font instruction +code copyright (c) 2001 by URW++ GmbH. All Rights Reserved. Luxi is a +registered trademark of Bigelow & Holmes Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of these Fonts and associated documentation files (the "Font Software"), to +deal in the Font Software, including without limitation the rights to use, +copy, merge, publish, distribute, sublicense, and/or sell copies of the Font +Software, and to permit persons to whom the Font Software is furnished to do +so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software. + +The Font Software may not be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may not be modified nor may +additional glyphs or characters be added to the Fonts. This License becomes +null and void when the Fonts or Font Software have been modified. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BIGELOW & HOLMES INC. OR URW++ +GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY +GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR +INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT +SOFTWARE. + +Except as contained in this notice, the names of Bigelow & Holmes Inc. and +URW++ GmbH. shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Font Software without prior written +authorization from Bigelow & Holmes Inc. and URW++ GmbH. + +For further information, contact: + +info@urwpp.de or design@bigelowandholmes.com + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to zlib v1.2.5, which may be included +with JRE 8, JDK 8, and OpenJDK 8. + +--- begin of LICENSE --- + + version 1.2.5, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to the following which may be +included with JRE 8, JDK 8, and OpenJDK 8, except where noted: + + Apache Commons Math 2.2 + Apache Derby 10.10.1.2 [included with JDK 8] + Apache Jakarta BCEL 5.2 + Apache Jakarta Regexp 1.4 + Apache Santuario XML Security for Java 1.5.4 + Apache Xalan-Java 2.7.1 + Apache Xerces Java 2.10.0 + Apache XML Resolver 1.1 + Dynalink 0.5 + + +--- begin of LICENSE --- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + From 03067370322479bfb5fb9d649e2f824b74566a95 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Thu, 16 Jan 2014 14:25:51 +0100 Subject: [PATCH 100/265] 8029101: PPC64 (part 211): ordering of Independent Reads of Independent Writes Reviewed-by: dholmes, kvn --- hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 3 +++ .../share/vm/interpreter/bytecodeInterpreter.cpp | 3 +++ hotspot/src/share/vm/opto/library_call.cpp | 16 ++++++++++++---- hotspot/src/share/vm/opto/parse.hpp | 5 ++++- hotspot/src/share/vm/opto/parse1.cpp | 9 ++++++++- hotspot/src/share/vm/opto/parse3.cpp | 14 +++++++++++++- hotspot/src/share/vm/prims/unsafe.cpp | 3 +++ .../src/share/vm/utilities/globalDefinitions.hpp | 11 +++++++++++ 8 files changed, 57 insertions(+), 7 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index aa8b89f901c..4cd5efdd4c3 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -37,4 +37,7 @@ const int StackAlignmentInBytes = 16; // signatures accordingly. const bool CCallingConventionRequiresIntsAsLongs = true; +// The PPC CPUs are NOT multiple-copy-atomic. +#define CPU_NOT_MULTIPLE_COPY_ATOMIC + #endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 73b4886a358..73c1575cdf3 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2034,6 +2034,9 @@ run: TosState tos_type = cache->flag_state(); int field_offset = cache->f2_as_index(); if (cache->is_volatile()) { + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + OrderAccess::fence(); + } if (tos_type == atos) { VERIFY_OOP(obj->obj_field_acquire(field_offset)); SET_STACK_OBJECT(obj->obj_field_acquire(field_offset), -1); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 8ad2fb7cff4..66141a1f9b9 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2627,8 +2627,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas // rough approximation of type. need_mem_bar = true; // For Stores, place a memory ordering barrier now. - if (is_store) + if (is_store) { insert_mem_bar(Op_MemBarRelease); + } else { + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { + insert_mem_bar(Op_MemBarVolatile); + } + } } // Memory barrier to prevent normal and 'unsafe' accesses from @@ -2717,10 +2722,13 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas } if (is_volatile) { - if (!is_store) + if (!is_store) { insert_mem_bar(Op_MemBarAcquire); - else - insert_mem_bar(Op_MemBarVolatile); + } else { + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + insert_mem_bar(Op_MemBarVolatile); + } + } } if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index f60e6a540ea..5a599e77c31 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -330,7 +330,8 @@ class Parse : public GraphKit { GraphKit _exits; // Record all normal returns and throws here. bool _wrote_final; // Did we write a final field? - bool _count_invocations; // update and test invocation counter + bool _wrote_volatile; // Did we write a volatile field? + bool _count_invocations; // update and test invocation counter bool _method_data_update; // update method data oop Node* _alloc_with_final; // An allocation node with final field @@ -373,6 +374,8 @@ class Parse : public GraphKit { GraphKit& exits() { return _exits; } bool wrote_final() const { return _wrote_final; } void set_wrote_final(bool z) { _wrote_final = z; } + bool wrote_volatile() const { return _wrote_volatile; } + void set_wrote_volatile(bool z) { _wrote_volatile = z; } bool count_invocations() const { return _count_invocations; } bool method_data_update() const { return _method_data_update; } Node* alloc_with_final() const { return _alloc_with_final; } diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index ac432ea3ea7..81e1c96c7ba 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -390,6 +390,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Pars _expected_uses = expected_uses; _depth = 1 + (caller->has_method() ? caller->depth() : 0); _wrote_final = false; + _wrote_volatile = false; _alloc_with_final = NULL; _entry_bci = InvocationEntryBci; _tf = NULL; @@ -907,7 +908,13 @@ void Parse::do_exits() { Node* iophi = _exits.i_o(); _exits.set_i_o(gvn().transform(iophi)); - if (wrote_final()) { + // On PPC64, also add MemBarRelease for constructors which write + // volatile fields. As support_IRIW_for_not_multiple_copy_atomic_cpu + // is set on PPC64, no sync instruction is issued after volatile + // stores. We want to quarantee the same behaviour as on platforms + // with total store order, although this is not required by the Java + // memory model. So as with finals, we add a barrier here. + if (wrote_final() PPC64_ONLY(|| (wrote_volatile() && method()->is_initializer()))) { // This method (which must be a constructor by the rules of Java) // wrote a final. The effects of all initializations must be // committed to memory before any code after the constructor diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index a1b0929af79..3deb9f4262c 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -227,6 +227,9 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { } else { type = Type::get_const_basic_type(bt); } + if (support_IRIW_for_not_multiple_copy_atomic_cpu && field->is_volatile()) { + insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier + } // Build the load. // MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; @@ -317,7 +320,16 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { // If reference is volatile, prevent following volatiles ops from // floating up before the volatile write. if (is_vol) { - insert_mem_bar(Op_MemBarVolatile); // Use fat membar + // If not multiple copy atomic, we do the MemBarVolatile before the load. + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + insert_mem_bar(Op_MemBarVolatile); // Use fat membar + } + // Remember we wrote a volatile field. + // For not multiple copy atomic cpu (ppc64) a barrier should be issued + // in constructors which have such stores. See do_exits() in parse1.cpp. + if (is_field) { + set_wrote_volatile(true); + } } // If the field is final, the rules of Java say we are in or . diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 2e432264b6e..8daafcd8949 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -162,6 +162,9 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ + if (support_IRIW_for_not_multiple_copy_atomic_cpu) { \ + OrderAccess::fence(); \ + } \ volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset)); #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index e522a98d796..6461d8303da 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -398,6 +398,17 @@ const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlass #define PLATFORM_NATIVE_STACK_WALKING_SUPPORTED 1 #endif +// To assure the IRIW property on processors that are not multiple copy +// atomic, sync instructions must be issued between volatile reads to +// assure their ordering, instead of after volatile stores. +// (See "A Tutorial Introduction to the ARM and POWER Relaxed Memory Models" +// by Luc Maranget, Susmit Sarkar and Peter Sewell, INRIA/Cambridge) +#ifdef CPU_NOT_MULTIPLE_COPY_ATOMIC +const bool support_IRIW_for_not_multiple_copy_atomic_cpu = true; +#else +const bool support_IRIW_for_not_multiple_copy_atomic_cpu = false; +#endif + // The byte alignment to be used by Arena::Amalloc. See bugid 4169348. // Note: this value must be a power of 2 From e2fecea88e5d388df81cae186caf3439f95eb1d0 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 24 Feb 2014 15:12:26 -0800 Subject: [PATCH 101/265] 8033805: Move Fast_Lock/Fast_Unlock code from .ad files to macroassembler Consolidated C2 x86 locking code in one place in macroAssembler_x86.cpp. Reviewed-by: roland --- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 1225 ++++++++++++----- hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 7 +- hotspot/src/cpu/x86/vm/x86_32.ad | 561 +------- hotspot/src/cpu/x86/vm/x86_64.ad | 243 +--- 4 files changed, 880 insertions(+), 1156 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index b4797bf3a39..74fa1b298ac 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -98,217 +98,6 @@ Address MacroAssembler::as_Address(ArrayAddress adr) { return Address::make_array(adr); } -int MacroAssembler::biased_locking_enter(Register lock_reg, - Register obj_reg, - Register swap_reg, - Register tmp_reg, - bool swap_reg_contains_mark, - Label& done, - Label* slow_case, - BiasedLockingCounters* counters) { - assert(UseBiasedLocking, "why call this otherwise?"); - assert(swap_reg == rax, "swap_reg must be rax, for cmpxchg"); - assert_different_registers(lock_reg, obj_reg, swap_reg); - - if (PrintBiasedLockingStatistics && counters == NULL) - counters = BiasedLocking::counters(); - - bool need_tmp_reg = false; - if (tmp_reg == noreg) { - need_tmp_reg = true; - tmp_reg = lock_reg; - } else { - assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); - } - assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); - Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); - Address saved_mark_addr(lock_reg, 0); - - // Biased locking - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits - // First check to see whether biasing is even enabled for this object - Label cas_label; - int null_check_offset = -1; - if (!swap_reg_contains_mark) { - null_check_offset = offset(); - movl(swap_reg, mark_addr); - } - if (need_tmp_reg) { - push(tmp_reg); - } - movl(tmp_reg, swap_reg); - andl(tmp_reg, markOopDesc::biased_lock_mask_in_place); - cmpl(tmp_reg, markOopDesc::biased_lock_pattern); - if (need_tmp_reg) { - pop(tmp_reg); - } - jcc(Assembler::notEqual, cas_label); - // The bias pattern is present in the object's header. Need to check - // whether the bias owner and the epoch are both still current. - // Note that because there is no current thread register on x86 we - // need to store off the mark word we read out of the object to - // avoid reloading it and needing to recheck invariants below. This - // store is unfortunate but it makes the overall code shorter and - // simpler. - movl(saved_mark_addr, swap_reg); - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - xorl(swap_reg, tmp_reg); - if (swap_reg_contains_mark) { - null_check_offset = offset(); - } - movl(tmp_reg, klass_addr); - xorl(swap_reg, Address(tmp_reg, Klass::prototype_header_offset())); - andl(swap_reg, ~((int) markOopDesc::age_mask_in_place)); - if (need_tmp_reg) { - pop(tmp_reg); - } - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->biased_lock_entry_count_addr())); - } - jcc(Assembler::equal, done); - - Label try_revoke_bias; - Label try_rebias; - - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - testl(swap_reg, markOopDesc::biased_lock_mask_in_place); - jcc(Assembler::notZero, try_revoke_bias); - - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - testl(swap_reg, markOopDesc::epoch_mask_in_place); - jcc(Assembler::notZero, try_rebias); - - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - movl(swap_reg, saved_mark_addr); - andl(swap_reg, - markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - orl(tmp_reg, swap_reg); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->anonymously_biased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_rebias); - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - movl(swap_reg, klass_addr); - orl(tmp_reg, Address(swap_reg, Klass::prototype_header_offset())); - movl(swap_reg, saved_mark_addr); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->rebiased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_revoke_bias); - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - movl(swap_reg, saved_mark_addr); - if (need_tmp_reg) { - push(tmp_reg); - } - movl(tmp_reg, klass_addr); - movl(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset())); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->revoked_lock_entry_count_addr())); - } - - bind(cas_label); - - return null_check_offset; -} void MacroAssembler::call_VM_leaf_base(address entry_point, int number_of_arguments) { call(RuntimeAddress(entry_point)); @@ -726,165 +515,6 @@ Address MacroAssembler::as_Address(ArrayAddress adr) { return array; } -int MacroAssembler::biased_locking_enter(Register lock_reg, - Register obj_reg, - Register swap_reg, - Register tmp_reg, - bool swap_reg_contains_mark, - Label& done, - Label* slow_case, - BiasedLockingCounters* counters) { - assert(UseBiasedLocking, "why call this otherwise?"); - assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq"); - assert(tmp_reg != noreg, "tmp_reg must be supplied"); - assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); - assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); - Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address saved_mark_addr(lock_reg, 0); - - if (PrintBiasedLockingStatistics && counters == NULL) - counters = BiasedLocking::counters(); - - // Biased locking - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits - // First check to see whether biasing is even enabled for this object - Label cas_label; - int null_check_offset = -1; - if (!swap_reg_contains_mark) { - null_check_offset = offset(); - movq(swap_reg, mark_addr); - } - movq(tmp_reg, swap_reg); - andq(tmp_reg, markOopDesc::biased_lock_mask_in_place); - cmpq(tmp_reg, markOopDesc::biased_lock_pattern); - jcc(Assembler::notEqual, cas_label); - // The bias pattern is present in the object's header. Need to check - // whether the bias owner and the epoch are both still current. - load_prototype_header(tmp_reg, obj_reg); - orq(tmp_reg, r15_thread); - xorq(tmp_reg, swap_reg); - andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); - } - jcc(Assembler::equal, done); - - Label try_revoke_bias; - Label try_rebias; - - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - testq(tmp_reg, markOopDesc::biased_lock_mask_in_place); - jcc(Assembler::notZero, try_revoke_bias); - - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - testq(tmp_reg, markOopDesc::epoch_mask_in_place); - jcc(Assembler::notZero, try_rebias); - - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - andq(swap_reg, - markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); - movq(tmp_reg, swap_reg); - orq(tmp_reg, r15_thread); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_rebias); - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_prototype_header(tmp_reg, obj_reg); - orq(tmp_reg, r15_thread); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_revoke_bias); - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_prototype_header(tmp_reg, obj_reg); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->revoked_lock_entry_count_addr())); - } - - bind(cas_label); - - return null_check_offset; -} - void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) { Label L, E; @@ -1360,9 +990,16 @@ void MacroAssembler::andptr(Register dst, int32_t imm32) { void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { pushf(); - if (os::is_MP()) - lock(); - incrementl(counter_addr); + if (reachable(counter_addr)) { + if (os::is_MP()) + lock(); + incrementl(as_Address(counter_addr)); + } else { + lea(rscratch1, counter_addr); + if (os::is_MP()) + lock(); + incrementl(Address(rscratch1, 0)); + } popf(); } @@ -1393,6 +1030,234 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) { } } +int MacroAssembler::biased_locking_enter(Register lock_reg, + Register obj_reg, + Register swap_reg, + Register tmp_reg, + bool swap_reg_contains_mark, + Label& done, + Label* slow_case, + BiasedLockingCounters* counters) { + assert(UseBiasedLocking, "why call this otherwise?"); + assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq"); + LP64_ONLY( assert(tmp_reg != noreg, "tmp_reg must be supplied"); ) + bool need_tmp_reg = false; + if (tmp_reg == noreg) { + need_tmp_reg = true; + tmp_reg = lock_reg; + assert_different_registers(lock_reg, obj_reg, swap_reg); + } else { + assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); + } + assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); + Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); + Address saved_mark_addr(lock_reg, 0); + + if (PrintBiasedLockingStatistics && counters == NULL) { + counters = BiasedLocking::counters(); + } + // Biased locking + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits + // First check to see whether biasing is even enabled for this object + Label cas_label; + int null_check_offset = -1; + if (!swap_reg_contains_mark) { + null_check_offset = offset(); + movptr(swap_reg, mark_addr); + } + if (need_tmp_reg) { + push(tmp_reg); + } + movptr(tmp_reg, swap_reg); + andptr(tmp_reg, markOopDesc::biased_lock_mask_in_place); + cmpptr(tmp_reg, markOopDesc::biased_lock_pattern); + if (need_tmp_reg) { + pop(tmp_reg); + } + jcc(Assembler::notEqual, cas_label); + // The bias pattern is present in the object's header. Need to check + // whether the bias owner and the epoch are both still current. +#ifndef _LP64 + // Note that because there is no current thread register on x86_32 we + // need to store off the mark word we read out of the object to + // avoid reloading it and needing to recheck invariants below. This + // store is unfortunate but it makes the overall code shorter and + // simpler. + movptr(saved_mark_addr, swap_reg); +#endif + if (need_tmp_reg) { + push(tmp_reg); + } + if (swap_reg_contains_mark) { + null_check_offset = offset(); + } + load_prototype_header(tmp_reg, obj_reg); +#ifdef _LP64 + orptr(tmp_reg, r15_thread); + xorptr(tmp_reg, swap_reg); + Register header_reg = tmp_reg; +#else + xorptr(tmp_reg, swap_reg); + get_thread(swap_reg); + xorptr(swap_reg, tmp_reg); + Register header_reg = swap_reg; +#endif + andptr(header_reg, ~((int) markOopDesc::age_mask_in_place)); + if (need_tmp_reg) { + pop(tmp_reg); + } + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->biased_lock_entry_count_addr())); + } + jcc(Assembler::equal, done); + + Label try_revoke_bias; + Label try_rebias; + + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + testptr(header_reg, markOopDesc::biased_lock_mask_in_place); + jccb(Assembler::notZero, try_revoke_bias); + + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + testptr(header_reg, markOopDesc::epoch_mask_in_place); + jccb(Assembler::notZero, try_rebias); + + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + NOT_LP64( movptr(swap_reg, saved_mark_addr); ) + andptr(swap_reg, + markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); + if (need_tmp_reg) { + push(tmp_reg); + } +#ifdef _LP64 + movptr(tmp_reg, swap_reg); + orptr(tmp_reg, r15_thread); +#else + get_thread(tmp_reg); + orptr(tmp_reg, swap_reg); +#endif + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg + if (need_tmp_reg) { + pop(tmp_reg); + } + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_rebias); + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + if (need_tmp_reg) { + push(tmp_reg); + } + load_prototype_header(tmp_reg, obj_reg); +#ifdef _LP64 + orptr(tmp_reg, r15_thread); +#else + get_thread(swap_reg); + orptr(tmp_reg, swap_reg); + movptr(swap_reg, saved_mark_addr); +#endif + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg + if (need_tmp_reg) { + pop(tmp_reg); + } + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_revoke_bias); + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + NOT_LP64( movptr(swap_reg, saved_mark_addr); ) + if (need_tmp_reg) { + push(tmp_reg); + } + load_prototype_header(tmp_reg, obj_reg); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg + if (need_tmp_reg) { + pop(tmp_reg); + } + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->revoked_lock_entry_count_addr())); + } + + bind(cas_label); + + return null_check_offset; +} + void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, Label& done) { assert(UseBiasedLocking, "why call this otherwise?"); @@ -1408,6 +1273,620 @@ void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, La jcc(Assembler::equal, done); } +#ifdef COMPILER2 +// Fast_Lock and Fast_Unlock used by C2 + +// Because the transitions from emitted code to the runtime +// monitorenter/exit helper stubs are so slow it's critical that +// we inline both the stack-locking fast-path and the inflated fast path. +// +// See also: cmpFastLock and cmpFastUnlock. +// +// What follows is a specialized inline transliteration of the code +// in slow_enter() and slow_exit(). If we're concerned about I$ bloat +// another option would be to emit TrySlowEnter and TrySlowExit methods +// at startup-time. These methods would accept arguments as +// (rax,=Obj, rbx=Self, rcx=box, rdx=Scratch) and return success-failure +// indications in the icc.ZFlag. Fast_Lock and Fast_Unlock would simply +// marshal the arguments and emit calls to TrySlowEnter and TrySlowExit. +// In practice, however, the # of lock sites is bounded and is usually small. +// Besides the call overhead, TrySlowEnter and TrySlowExit might suffer +// if the processor uses simple bimodal branch predictors keyed by EIP +// Since the helper routines would be called from multiple synchronization +// sites. +// +// An even better approach would be write "MonitorEnter()" and "MonitorExit()" +// in java - using j.u.c and unsafe - and just bind the lock and unlock sites +// to those specialized methods. That'd give us a mostly platform-independent +// implementation that the JITs could optimize and inline at their pleasure. +// Done correctly, the only time we'd need to cross to native could would be +// to park() or unpark() threads. We'd also need a few more unsafe operators +// to (a) prevent compiler-JIT reordering of non-volatile accesses, and +// (b) explicit barriers or fence operations. +// +// TODO: +// +// * Arrange for C2 to pass "Self" into Fast_Lock and Fast_Unlock in one of the registers (scr). +// This avoids manifesting the Self pointer in the Fast_Lock and Fast_Unlock terminals. +// Given TLAB allocation, Self is usually manifested in a register, so passing it into +// the lock operators would typically be faster than reifying Self. +// +// * Ideally I'd define the primitives as: +// fast_lock (nax Obj, nax box, EAX tmp, nax scr) where box, tmp and scr are KILLED. +// fast_unlock (nax Obj, EAX box, nax tmp) where box and tmp are KILLED +// Unfortunately ADLC bugs prevent us from expressing the ideal form. +// Instead, we're stuck with a rather awkward and brittle register assignments below. +// Furthermore the register assignments are overconstrained, possibly resulting in +// sub-optimal code near the synchronization site. +// +// * Eliminate the sp-proximity tests and just use "== Self" tests instead. +// Alternately, use a better sp-proximity test. +// +// * Currently ObjectMonitor._Owner can hold either an sp value or a (THREAD *) value. +// Either one is sufficient to uniquely identify a thread. +// TODO: eliminate use of sp in _owner and use get_thread(tr) instead. +// +// * Intrinsify notify() and notifyAll() for the common cases where the +// object is locked by the calling thread but the waitlist is empty. +// avoid the expensive JNI call to JVM_Notify() and JVM_NotifyAll(). +// +// * use jccb and jmpb instead of jcc and jmp to improve code density. +// But beware of excessive branch density on AMD Opterons. +// +// * Both Fast_Lock and Fast_Unlock set the ICC.ZF to indicate success +// or failure of the fast-path. If the fast-path fails then we pass +// control to the slow-path, typically in C. In Fast_Lock and +// Fast_Unlock we often branch to DONE_LABEL, just to find that C2 +// will emit a conditional branch immediately after the node. +// So we have branches to branches and lots of ICC.ZF games. +// Instead, it might be better to have C2 pass a "FailureLabel" +// into Fast_Lock and Fast_Unlock. In the case of success, control +// will drop through the node. ICC.ZF is undefined at exit. +// In the case of failure, the node will branch directly to the +// FailureLabel + + +// obj: object to lock +// box: on-stack box address (displaced header location) - KILLED +// rax,: tmp -- KILLED +// scr: tmp -- KILLED +void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, Register scrReg, BiasedLockingCounters* counters) { + // Ensure the register assignents are disjoint + guarantee (objReg != boxReg, ""); + guarantee (objReg != tmpReg, ""); + guarantee (objReg != scrReg, ""); + guarantee (boxReg != tmpReg, ""); + guarantee (boxReg != scrReg, ""); + guarantee (tmpReg == rax, ""); + + if (counters != NULL) { + atomic_incl(ExternalAddress((address)counters->total_entry_count_addr())); + } + if (EmitSync & 1) { + // set box->dhw = unused_mark (3) + // Force all sync thru slow-path: slow_enter() and slow_exit() + movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); + cmpptr (rsp, (int32_t)NULL_WORD); + } else + if (EmitSync & 2) { + Label DONE_LABEL ; + if (UseBiasedLocking) { + // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument. + biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, counters); + } + + movptr(tmpReg, Address(objReg, 0)); // fetch markword + orptr (tmpReg, 0x1); + movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS + if (os::is_MP()) { + lock(); + } + cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg + jccb(Assembler::equal, DONE_LABEL); + // Recursive locking + subptr(tmpReg, rsp); + andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); + movptr(Address(boxReg, 0), tmpReg); + bind(DONE_LABEL); + } else { + // Possible cases that we'll encounter in fast_lock + // ------------------------------------------------ + // * Inflated + // -- unlocked + // -- Locked + // = by self + // = by other + // * biased + // -- by Self + // -- by other + // * neutral + // * stack-locked + // -- by self + // = sp-proximity test hits + // = sp-proximity test generates false-negative + // -- by other + // + + Label IsInflated, DONE_LABEL; + + // it's stack-locked, biased or neutral + // TODO: optimize away redundant LDs of obj->mark and improve the markword triage + // order to reduce the number of conditional branches in the most common cases. + // Beware -- there's a subtle invariant that fetch of the markword + // at [FETCH], below, will never observe a biased encoding (*101b). + // If this invariant is not held we risk exclusion (safety) failure. + if (UseBiasedLocking && !UseOptoBiasInlining) { + biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, counters); + } + + movptr(tmpReg, Address(objReg, 0)); // [FETCH] + testl (tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jccb (Assembler::notZero, IsInflated); + + // Attempt stack-locking ... + orptr (tmpReg, 0x1); + movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS + if (os::is_MP()) { + lock(); + } + cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg + if (counters != NULL) { + cond_inc32(Assembler::equal, + ExternalAddress((address)counters->fast_path_entry_count_addr())); + } + jccb(Assembler::equal, DONE_LABEL); + + // Recursive locking + subptr(tmpReg, rsp); + andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); + movptr(Address(boxReg, 0), tmpReg); + if (counters != NULL) { + cond_inc32(Assembler::equal, + ExternalAddress((address)counters->fast_path_entry_count_addr())); + } + jmpb(DONE_LABEL); + + bind(IsInflated); +#ifndef _LP64 + // The object is inflated. + // + // TODO-FIXME: eliminate the ugly use of manifest constants: + // Use markOopDesc::monitor_value instead of "2". + // use markOop::unused_mark() instead of "3". + // The tmpReg value is an objectMonitor reference ORed with + // markOopDesc::monitor_value (2). We can either convert tmpReg to an + // objectmonitor pointer by masking off the "2" bit or we can just + // use tmpReg as an objectmonitor pointer but bias the objectmonitor + // field offsets with "-2" to compensate for and annul the low-order tag bit. + // + // I use the latter as it avoids AGI stalls. + // As such, we write "mov r, [tmpReg+OFFSETOF(Owner)-2]" + // instead of "mov r, [tmpReg+OFFSETOF(Owner)]". + // + #define OFFSET_SKEWED(f) ((ObjectMonitor::f ## _offset_in_bytes())-2) + + // boxReg refers to the on-stack BasicLock in the current frame. + // We'd like to write: + // set box->_displaced_header = markOop::unused_mark(). Any non-0 value suffices. + // This is convenient but results a ST-before-CAS penalty. The following CAS suffers + // additional latency as we have another ST in the store buffer that must drain. + + if (EmitSync & 8192) { + movptr(Address(boxReg, 0), 3); // results in ST-before-CAS penalty + get_thread (scrReg); + movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] + movptr(tmpReg, NULL_WORD); // consider: xor vs mov + if (os::is_MP()) { + lock(); + } + cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); + } else + if ((EmitSync & 128) == 0) { // avoid ST-before-CAS + movptr(scrReg, boxReg); + movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] + + // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes + if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { + // prefetchw [eax + Offset(_owner)-2] + prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + } + + if ((EmitSync & 64) == 0) { + // Optimistic form: consider XORL tmpReg,tmpReg + movptr(tmpReg, NULL_WORD); + } else { + // Can suffer RTS->RTO upgrades on shared or cold $ lines + // Test-And-CAS instead of CAS + movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner + testptr(tmpReg, tmpReg); // Locked ? + jccb (Assembler::notZero, DONE_LABEL); + } + + // Appears unlocked - try to swing _owner from null to non-null. + // Ideally, I'd manifest "Self" with get_thread and then attempt + // to CAS the register containing Self into m->Owner. + // But we don't have enough registers, so instead we can either try to CAS + // rsp or the address of the box (in scr) into &m->owner. If the CAS succeeds + // we later store "Self" into m->Owner. Transiently storing a stack address + // (rsp or the address of the box) into m->owner is harmless. + // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. + if (os::is_MP()) { + lock(); + } + cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); + movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3 + jccb (Assembler::notZero, DONE_LABEL); + get_thread (scrReg); // beware: clobbers ICCs + movptr(Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2), scrReg); + xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success + + // If the CAS fails we can either retry or pass control to the slow-path. + // We use the latter tactic. + // Pass the CAS result in the icc.ZFlag into DONE_LABEL + // If the CAS was successful ... + // Self has acquired the lock + // Invariant: m->_recursions should already be 0, so we don't need to explicitly set it. + // Intentional fall-through into DONE_LABEL ... + } else { + movptr(Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())); // results in ST-before-CAS penalty + movptr(boxReg, tmpReg); + + // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes + if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { + // prefetchw [eax + Offset(_owner)-2] + prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + } + + if ((EmitSync & 64) == 0) { + // Optimistic form + xorptr (tmpReg, tmpReg); + } else { + // Can suffer RTS->RTO upgrades on shared or cold $ lines + movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner + testptr(tmpReg, tmpReg); // Locked ? + jccb (Assembler::notZero, DONE_LABEL); + } + + // Appears unlocked - try to swing _owner from null to non-null. + // Use either "Self" (in scr) or rsp as thread identity in _owner. + // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. + get_thread (scrReg); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); + + // If the CAS fails we can either retry or pass control to the slow-path. + // We use the latter tactic. + // Pass the CAS result in the icc.ZFlag into DONE_LABEL + // If the CAS was successful ... + // Self has acquired the lock + // Invariant: m->_recursions should already be 0, so we don't need to explicitly set it. + // Intentional fall-through into DONE_LABEL ... + } +#else // _LP64 + // It's inflated + + // TODO: someday avoid the ST-before-CAS penalty by + // relocating (deferring) the following ST. + // We should also think about trying a CAS without having + // fetched _owner. If the CAS is successful we may + // avoid an RTO->RTS upgrade on the $line. + + // Without cast to int32_t a movptr will destroy r10 which is typically obj + movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); + + mov (boxReg, tmpReg); + movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); + testptr(tmpReg, tmpReg); + jccb (Assembler::notZero, DONE_LABEL); + + // It's inflated and appears unlocked + if (os::is_MP()) { + lock(); + } + cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); + // Intentional fall-through into DONE_LABEL ... + +#endif + + // DONE_LABEL is a hot target - we'd really like to place it at the + // start of cache line by padding with NOPs. + // See the AMD and Intel software optimization manuals for the + // most efficient "long" NOP encodings. + // Unfortunately none of our alignment mechanisms suffice. + bind(DONE_LABEL); + + // At DONE_LABEL the icc ZFlag is set as follows ... + // Fast_Unlock uses the same protocol. + // ZFlag == 1 -> Success + // ZFlag == 0 -> Failure - force control through the slow-path + } +} + +// obj: object to unlock +// box: box address (displaced header location), killed. Must be EAX. +// tmp: killed, cannot be obj nor box. +// +// Some commentary on balanced locking: +// +// Fast_Lock and Fast_Unlock are emitted only for provably balanced lock sites. +// Methods that don't have provably balanced locking are forced to run in the +// interpreter - such methods won't be compiled to use fast_lock and fast_unlock. +// The interpreter provides two properties: +// I1: At return-time the interpreter automatically and quietly unlocks any +// objects acquired the current activation (frame). Recall that the +// interpreter maintains an on-stack list of locks currently held by +// a frame. +// I2: If a method attempts to unlock an object that is not held by the +// the frame the interpreter throws IMSX. +// +// Lets say A(), which has provably balanced locking, acquires O and then calls B(). +// B() doesn't have provably balanced locking so it runs in the interpreter. +// Control returns to A() and A() unlocks O. By I1 and I2, above, we know that O +// is still locked by A(). +// +// The only other source of unbalanced locking would be JNI. The "Java Native Interface: +// Programmer's Guide and Specification" claims that an object locked by jni_monitorenter +// should not be unlocked by "normal" java-level locking and vice-versa. The specification +// doesn't specify what will occur if a program engages in such mixed-mode locking, however. + +void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) { + guarantee (objReg != boxReg, ""); + guarantee (objReg != tmpReg, ""); + guarantee (boxReg != tmpReg, ""); + guarantee (boxReg == rax, ""); + + if (EmitSync & 4) { + // Disable - inhibit all inlining. Force control through the slow-path + cmpptr (rsp, 0); + } else + if (EmitSync & 8) { + Label DONE_LABEL; + if (UseBiasedLocking) { + biased_locking_exit(objReg, tmpReg, DONE_LABEL); + } + // Classic stack-locking code ... + // Check whether the displaced header is 0 + //(=> recursive unlock) + movptr(tmpReg, Address(boxReg, 0)); + testptr(tmpReg, tmpReg); + jccb(Assembler::zero, DONE_LABEL); + // If not recursive lock, reset the header to displaced header + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + bind(DONE_LABEL); + } else { + Label DONE_LABEL, Stacked, CheckSucc; + + // Critically, the biased locking test must have precedence over + // and appear before the (box->dhw == 0) recursive stack-lock test. + if (UseBiasedLocking && !UseOptoBiasInlining) { + biased_locking_exit(objReg, tmpReg, DONE_LABEL); + } + + cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header + movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword + jccb (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock + + testptr(tmpReg, 0x02); // Inflated? + jccb (Assembler::zero, Stacked); + + // It's inflated. + // Despite our balanced locking property we still check that m->_owner == Self + // as java routines or native JNI code called by this thread might + // have released the lock. + // Refer to the comments in synchronizer.cpp for how we might encode extra + // state in _succ so we can avoid fetching EntryList|cxq. + // + // I'd like to add more cases in fast_lock() and fast_unlock() -- + // such as recursive enter and exit -- but we have to be wary of + // I$ bloat, T$ effects and BP$ effects. + // + // If there's no contention try a 1-0 exit. That is, exit without + // a costly MEMBAR or CAS. See synchronizer.cpp for details on how + // we detect and recover from the race that the 1-0 exit admits. + // + // Conceptually Fast_Unlock() must execute a STST|LDST "release" barrier + // before it STs null into _owner, releasing the lock. Updates + // to data protected by the critical section must be visible before + // we drop the lock (and thus before any other thread could acquire + // the lock and observe the fields protected by the lock). + // IA32's memory-model is SPO, so STs are ordered with respect to + // each other and there's no need for an explicit barrier (fence). + // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. +#ifndef _LP64 + get_thread (boxReg); + if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { + // prefetchw [ebx + Offset(_owner)-2] + prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + } + + // Note that we could employ various encoding schemes to reduce + // the number of loads below (currently 4) to just 2 or 3. + // Refer to the comments in synchronizer.cpp. + // In practice the chain of fetches doesn't seem to impact performance, however. + if ((EmitSync & 65536) == 0 && (EmitSync & 256)) { + // Attempt to reduce branch density - AMD's branch predictor. + xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); + orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); + orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); + jccb (Assembler::notZero, DONE_LABEL); + movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); + jmpb (DONE_LABEL); + } else { + xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); + jccb (Assembler::notZero, DONE_LABEL); + movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); + orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); + jccb (Assembler::notZero, CheckSucc); + movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); + jmpb (DONE_LABEL); + } + + // The Following code fragment (EmitSync & 65536) improves the performance of + // contended applications and contended synchronization microbenchmarks. + // Unfortunately the emission of the code - even though not executed - causes regressions + // in scimark and jetstream, evidently because of $ effects. Replacing the code + // with an equal number of never-executed NOPs results in the same regression. + // We leave it off by default. + + if ((EmitSync & 65536) != 0) { + Label LSuccess, LGoSlowPath ; + + bind (CheckSucc); + + // Optional pre-test ... it's safe to elide this + if ((EmitSync & 16) == 0) { + cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD); + jccb (Assembler::zero, LGoSlowPath); + } + + // We have a classic Dekker-style idiom: + // ST m->_owner = 0 ; MEMBAR; LD m->_succ + // There are a number of ways to implement the barrier: + // (1) lock:andl &m->_owner, 0 + // is fast, but mask doesn't currently support the "ANDL M,IMM32" form. + // LOCK: ANDL [ebx+Offset(_Owner)-2], 0 + // Encodes as 81 31 OFF32 IMM32 or 83 63 OFF8 IMM8 + // (2) If supported, an explicit MFENCE is appealing. + // In older IA32 processors MFENCE is slower than lock:add or xchg + // particularly if the write-buffer is full as might be the case if + // if stores closely precede the fence or fence-equivalent instruction. + // In more modern implementations MFENCE appears faster, however. + // (3) In lieu of an explicit fence, use lock:addl to the top-of-stack + // The $lines underlying the top-of-stack should be in M-state. + // The locked add instruction is serializing, of course. + // (4) Use xchg, which is serializing + // mov boxReg, 0; xchgl boxReg, [tmpReg + Offset(_owner)-2] also works + // (5) ST m->_owner = 0 and then execute lock:orl &m->_succ, 0. + // The integer condition codes will tell us if succ was 0. + // Since _succ and _owner should reside in the same $line and + // we just stored into _owner, it's likely that the $line + // remains in M-state for the lock:orl. + // + // We currently use (3), although it's likely that switching to (2) + // is correct for the future. + + movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); + if (os::is_MP()) { + if (VM_Version::supports_sse2() && 1 == FenceInstruction) { + mfence(); + } else { + lock (); addptr(Address(rsp, 0), 0); + } + } + // Ratify _succ remains non-null + cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0); + jccb (Assembler::notZero, LSuccess); + + xorptr(boxReg, boxReg); // box is really EAX + if (os::is_MP()) { lock(); } + cmpxchgptr(rsp, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + jccb (Assembler::notEqual, LSuccess); + // Since we're low on registers we installed rsp as a placeholding in _owner. + // Now install Self over rsp. This is safe as we're transitioning from + // non-null to non=null + get_thread (boxReg); + movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), boxReg); + // Intentional fall-through into LGoSlowPath ... + + bind (LGoSlowPath); + orptr(boxReg, 1); // set ICC.ZF=0 to indicate failure + jmpb (DONE_LABEL); + + bind (LSuccess); + xorptr(boxReg, boxReg); // set ICC.ZF=1 to indicate success + jmpb (DONE_LABEL); + } + + bind (Stacked); + // It's not inflated and it's not recursively stack-locked and it's not biased. + // It must be stack-locked. + // Try to reset the header to displaced header. + // The "box" value on the stack is stable, so we can reload + // and be assured we observe the same value as above. + movptr(tmpReg, Address(boxReg, 0)); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + // Intention fall-thru into DONE_LABEL + + // DONE_LABEL is a hot target - we'd really like to place it at the + // start of cache line by padding with NOPs. + // See the AMD and Intel software optimization manuals for the + // most efficient "long" NOP encodings. + // Unfortunately none of our alignment mechanisms suffice. + if ((EmitSync & 65536) == 0) { + bind (CheckSucc); + } +#else // _LP64 + // It's inflated + movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + xorptr(boxReg, r15_thread); + orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); + jccb (Assembler::notZero, DONE_LABEL); + movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); + orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); + jccb (Assembler::notZero, CheckSucc); + movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD); + jmpb (DONE_LABEL); + + if ((EmitSync & 65536) == 0) { + Label LSuccess, LGoSlowPath ; + bind (CheckSucc); + cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD); + jccb (Assembler::zero, LGoSlowPath); + + // I'd much rather use lock:andl m->_owner, 0 as it's faster than the + // the explicit ST;MEMBAR combination, but masm doesn't currently support + // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc + // are all faster when the write buffer is populated. + movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD); + if (os::is_MP()) { + lock (); addl (Address(rsp, 0), 0); + } + cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD); + jccb (Assembler::notZero, LSuccess); + + movptr (boxReg, (int32_t)NULL_WORD); // box is really EAX + if (os::is_MP()) { lock(); } + cmpxchgptr(r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); + jccb (Assembler::notEqual, LSuccess); + // Intentional fall-through into slow-path + + bind (LGoSlowPath); + orl (boxReg, 1); // set ICC.ZF=0 to indicate failure + jmpb (DONE_LABEL); + + bind (LSuccess); + testl (boxReg, 0); // set ICC.ZF=1 to indicate success + jmpb (DONE_LABEL); + } + + bind (Stacked); + movptr(tmpReg, Address (boxReg, 0)); // re-fetch + if (os::is_MP()) { lock(); } + cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + + if (EmitSync & 65536) { + bind (CheckSucc); + } +#endif + bind(DONE_LABEL); + // Avoid branch to branch on AMD processors + if (EmitSync & 32768) { + nop(); + } + } +} +#endif // COMPILER2 + void MacroAssembler::c2bool(Register x) { // implements x == 0 ? 0 : 1 // note: must only look at least-significant byte of x diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 198fc98e86a..6ac95774ba9 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -651,7 +651,12 @@ class MacroAssembler: public Assembler { Label& done, Label* slow_case = NULL, BiasedLockingCounters* counters = NULL); void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); - +#ifdef COMPILER2 + // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. + // See full desription in macroAssembler_x86.cpp. + void fast_lock(Register obj, Register box, Register tmp, Register scr, BiasedLockingCounters* counters); + void fast_unlock(Register obj, Register box, Register tmp); +#endif Condition negate_condition(Condition cond); diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index cc0dfaa110f..f13e5c17859 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -2918,542 +2918,6 @@ encode %{ emit_d8 (cbuf,0 ); %} - - // Because the transitions from emitted code to the runtime - // monitorenter/exit helper stubs are so slow it's critical that - // we inline both the stack-locking fast-path and the inflated fast path. - // - // See also: cmpFastLock and cmpFastUnlock. - // - // What follows is a specialized inline transliteration of the code - // in slow_enter() and slow_exit(). If we're concerned about I$ bloat - // another option would be to emit TrySlowEnter and TrySlowExit methods - // at startup-time. These methods would accept arguments as - // (rax,=Obj, rbx=Self, rcx=box, rdx=Scratch) and return success-failure - // indications in the icc.ZFlag. Fast_Lock and Fast_Unlock would simply - // marshal the arguments and emit calls to TrySlowEnter and TrySlowExit. - // In practice, however, the # of lock sites is bounded and is usually small. - // Besides the call overhead, TrySlowEnter and TrySlowExit might suffer - // if the processor uses simple bimodal branch predictors keyed by EIP - // Since the helper routines would be called from multiple synchronization - // sites. - // - // An even better approach would be write "MonitorEnter()" and "MonitorExit()" - // in java - using j.u.c and unsafe - and just bind the lock and unlock sites - // to those specialized methods. That'd give us a mostly platform-independent - // implementation that the JITs could optimize and inline at their pleasure. - // Done correctly, the only time we'd need to cross to native could would be - // to park() or unpark() threads. We'd also need a few more unsafe operators - // to (a) prevent compiler-JIT reordering of non-volatile accesses, and - // (b) explicit barriers or fence operations. - // - // TODO: - // - // * Arrange for C2 to pass "Self" into Fast_Lock and Fast_Unlock in one of the registers (scr). - // This avoids manifesting the Self pointer in the Fast_Lock and Fast_Unlock terminals. - // Given TLAB allocation, Self is usually manifested in a register, so passing it into - // the lock operators would typically be faster than reifying Self. - // - // * Ideally I'd define the primitives as: - // fast_lock (nax Obj, nax box, EAX tmp, nax scr) where box, tmp and scr are KILLED. - // fast_unlock (nax Obj, EAX box, nax tmp) where box and tmp are KILLED - // Unfortunately ADLC bugs prevent us from expressing the ideal form. - // Instead, we're stuck with a rather awkward and brittle register assignments below. - // Furthermore the register assignments are overconstrained, possibly resulting in - // sub-optimal code near the synchronization site. - // - // * Eliminate the sp-proximity tests and just use "== Self" tests instead. - // Alternately, use a better sp-proximity test. - // - // * Currently ObjectMonitor._Owner can hold either an sp value or a (THREAD *) value. - // Either one is sufficient to uniquely identify a thread. - // TODO: eliminate use of sp in _owner and use get_thread(tr) instead. - // - // * Intrinsify notify() and notifyAll() for the common cases where the - // object is locked by the calling thread but the waitlist is empty. - // avoid the expensive JNI call to JVM_Notify() and JVM_NotifyAll(). - // - // * use jccb and jmpb instead of jcc and jmp to improve code density. - // But beware of excessive branch density on AMD Opterons. - // - // * Both Fast_Lock and Fast_Unlock set the ICC.ZF to indicate success - // or failure of the fast-path. If the fast-path fails then we pass - // control to the slow-path, typically in C. In Fast_Lock and - // Fast_Unlock we often branch to DONE_LABEL, just to find that C2 - // will emit a conditional branch immediately after the node. - // So we have branches to branches and lots of ICC.ZF games. - // Instead, it might be better to have C2 pass a "FailureLabel" - // into Fast_Lock and Fast_Unlock. In the case of success, control - // will drop through the node. ICC.ZF is undefined at exit. - // In the case of failure, the node will branch directly to the - // FailureLabel - - - // obj: object to lock - // box: on-stack box address (displaced header location) - KILLED - // rax,: tmp -- KILLED - // scr: tmp -- KILLED - enc_class Fast_Lock( eRegP obj, eRegP box, eAXRegI tmp, eRegP scr ) %{ - - Register objReg = as_Register($obj$$reg); - Register boxReg = as_Register($box$$reg); - Register tmpReg = as_Register($tmp$$reg); - Register scrReg = as_Register($scr$$reg); - - // Ensure the register assignents are disjoint - guarantee (objReg != boxReg, "") ; - guarantee (objReg != tmpReg, "") ; - guarantee (objReg != scrReg, "") ; - guarantee (boxReg != tmpReg, "") ; - guarantee (boxReg != scrReg, "") ; - guarantee (tmpReg == as_Register(EAX_enc), "") ; - - MacroAssembler masm(&cbuf); - - if (_counters != NULL) { - masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); - } - if (EmitSync & 1) { - // set box->dhw = unused_mark (3) - // Force all sync thru slow-path: slow_enter() and slow_exit() - masm.movptr (Address(boxReg, 0), int32_t(markOopDesc::unused_mark())) ; - masm.cmpptr (rsp, (int32_t)0) ; - } else - if (EmitSync & 2) { - Label DONE_LABEL ; - if (UseBiasedLocking) { - // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument. - masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); - } - - masm.movptr(tmpReg, Address(objReg, 0)) ; // fetch markword - masm.orptr (tmpReg, 0x1); - masm.movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg - masm.jcc(Assembler::equal, DONE_LABEL); - // Recursive locking - masm.subptr(tmpReg, rsp); - masm.andptr(tmpReg, (int32_t) 0xFFFFF003 ); - masm.movptr(Address(boxReg, 0), tmpReg); - masm.bind(DONE_LABEL) ; - } else { - // Possible cases that we'll encounter in fast_lock - // ------------------------------------------------ - // * Inflated - // -- unlocked - // -- Locked - // = by self - // = by other - // * biased - // -- by Self - // -- by other - // * neutral - // * stack-locked - // -- by self - // = sp-proximity test hits - // = sp-proximity test generates false-negative - // -- by other - // - - Label IsInflated, DONE_LABEL, PopDone ; - - // TODO: optimize away redundant LDs of obj->mark and improve the markword triage - // order to reduce the number of conditional branches in the most common cases. - // Beware -- there's a subtle invariant that fetch of the markword - // at [FETCH], below, will never observe a biased encoding (*101b). - // If this invariant is not held we risk exclusion (safety) failure. - if (UseBiasedLocking && !UseOptoBiasInlining) { - masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); - } - - masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] - masm.testptr(tmpReg, 0x02) ; // Inflated v (Stack-locked or neutral) - masm.jccb (Assembler::notZero, IsInflated) ; - - // Attempt stack-locking ... - masm.orptr (tmpReg, 0x1); - masm.movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg - if (_counters != NULL) { - masm.cond_inc32(Assembler::equal, - ExternalAddress((address)_counters->fast_path_entry_count_addr())); - } - masm.jccb (Assembler::equal, DONE_LABEL); - - // Recursive locking - masm.subptr(tmpReg, rsp); - masm.andptr(tmpReg, 0xFFFFF003 ); - masm.movptr(Address(boxReg, 0), tmpReg); - if (_counters != NULL) { - masm.cond_inc32(Assembler::equal, - ExternalAddress((address)_counters->fast_path_entry_count_addr())); - } - masm.jmp (DONE_LABEL) ; - - masm.bind (IsInflated) ; - - // The object is inflated. - // - // TODO-FIXME: eliminate the ugly use of manifest constants: - // Use markOopDesc::monitor_value instead of "2". - // use markOop::unused_mark() instead of "3". - // The tmpReg value is an objectMonitor reference ORed with - // markOopDesc::monitor_value (2). We can either convert tmpReg to an - // objectmonitor pointer by masking off the "2" bit or we can just - // use tmpReg as an objectmonitor pointer but bias the objectmonitor - // field offsets with "-2" to compensate for and annul the low-order tag bit. - // - // I use the latter as it avoids AGI stalls. - // As such, we write "mov r, [tmpReg+OFFSETOF(Owner)-2]" - // instead of "mov r, [tmpReg+OFFSETOF(Owner)]". - // - #define OFFSET_SKEWED(f) ((ObjectMonitor::f ## _offset_in_bytes())-2) - - // boxReg refers to the on-stack BasicLock in the current frame. - // We'd like to write: - // set box->_displaced_header = markOop::unused_mark(). Any non-0 value suffices. - // This is convenient but results a ST-before-CAS penalty. The following CAS suffers - // additional latency as we have another ST in the store buffer that must drain. - - if (EmitSync & 8192) { - masm.movptr(Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty - masm.get_thread (scrReg) ; - masm.movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] - masm.movptr(tmpReg, NULL_WORD); // consider: xor vs mov - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - } else - if ((EmitSync & 128) == 0) { // avoid ST-before-CAS - masm.movptr(scrReg, boxReg) ; - masm.movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] - - // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes - if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { - // prefetchw [eax + Offset(_owner)-2] - masm.prefetchw(Address(rax, ObjectMonitor::owner_offset_in_bytes()-2)); - } - - if ((EmitSync & 64) == 0) { - // Optimistic form: consider XORL tmpReg,tmpReg - masm.movptr(tmpReg, NULL_WORD) ; - } else { - // Can suffer RTS->RTO upgrades on shared or cold $ lines - // Test-And-CAS instead of CAS - masm.movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; // rax, = m->_owner - masm.testptr(tmpReg, tmpReg) ; // Locked ? - masm.jccb (Assembler::notZero, DONE_LABEL) ; - } - - // Appears unlocked - try to swing _owner from null to non-null. - // Ideally, I'd manifest "Self" with get_thread and then attempt - // to CAS the register containing Self into m->Owner. - // But we don't have enough registers, so instead we can either try to CAS - // rsp or the address of the box (in scr) into &m->owner. If the CAS succeeds - // we later store "Self" into m->Owner. Transiently storing a stack address - // (rsp or the address of the box) into m->owner is harmless. - // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.movptr(Address(scrReg, 0), 3) ; // box->_displaced_header = 3 - masm.jccb (Assembler::notZero, DONE_LABEL) ; - masm.get_thread (scrReg) ; // beware: clobbers ICCs - masm.movptr(Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2), scrReg) ; - masm.xorptr(boxReg, boxReg) ; // set icc.ZFlag = 1 to indicate success - - // If the CAS fails we can either retry or pass control to the slow-path. - // We use the latter tactic. - // Pass the CAS result in the icc.ZFlag into DONE_LABEL - // If the CAS was successful ... - // Self has acquired the lock - // Invariant: m->_recursions should already be 0, so we don't need to explicitly set it. - // Intentional fall-through into DONE_LABEL ... - } else { - masm.movptr(Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty - masm.movptr(boxReg, tmpReg) ; - - // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes - if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { - // prefetchw [eax + Offset(_owner)-2] - masm.prefetchw(Address(rax, ObjectMonitor::owner_offset_in_bytes()-2)); - } - - if ((EmitSync & 64) == 0) { - // Optimistic form - masm.xorptr (tmpReg, tmpReg) ; - } else { - // Can suffer RTS->RTO upgrades on shared or cold $ lines - masm.movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; // rax, = m->_owner - masm.testptr(tmpReg, tmpReg) ; // Locked ? - masm.jccb (Assembler::notZero, DONE_LABEL) ; - } - - // Appears unlocked - try to swing _owner from null to non-null. - // Use either "Self" (in scr) or rsp as thread identity in _owner. - // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. - masm.get_thread (scrReg) ; - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - - // If the CAS fails we can either retry or pass control to the slow-path. - // We use the latter tactic. - // Pass the CAS result in the icc.ZFlag into DONE_LABEL - // If the CAS was successful ... - // Self has acquired the lock - // Invariant: m->_recursions should already be 0, so we don't need to explicitly set it. - // Intentional fall-through into DONE_LABEL ... - } - - // DONE_LABEL is a hot target - we'd really like to place it at the - // start of cache line by padding with NOPs. - // See the AMD and Intel software optimization manuals for the - // most efficient "long" NOP encodings. - // Unfortunately none of our alignment mechanisms suffice. - masm.bind(DONE_LABEL); - - // Avoid branch-to-branch on AMD processors - // This appears to be superstition. - if (EmitSync & 32) masm.nop() ; - - - // At DONE_LABEL the icc ZFlag is set as follows ... - // Fast_Unlock uses the same protocol. - // ZFlag == 1 -> Success - // ZFlag == 0 -> Failure - force control through the slow-path - } - %} - - // obj: object to unlock - // box: box address (displaced header location), killed. Must be EAX. - // rbx,: killed tmp; cannot be obj nor box. - // - // Some commentary on balanced locking: - // - // Fast_Lock and Fast_Unlock are emitted only for provably balanced lock sites. - // Methods that don't have provably balanced locking are forced to run in the - // interpreter - such methods won't be compiled to use fast_lock and fast_unlock. - // The interpreter provides two properties: - // I1: At return-time the interpreter automatically and quietly unlocks any - // objects acquired the current activation (frame). Recall that the - // interpreter maintains an on-stack list of locks currently held by - // a frame. - // I2: If a method attempts to unlock an object that is not held by the - // the frame the interpreter throws IMSX. - // - // Lets say A(), which has provably balanced locking, acquires O and then calls B(). - // B() doesn't have provably balanced locking so it runs in the interpreter. - // Control returns to A() and A() unlocks O. By I1 and I2, above, we know that O - // is still locked by A(). - // - // The only other source of unbalanced locking would be JNI. The "Java Native Interface: - // Programmer's Guide and Specification" claims that an object locked by jni_monitorenter - // should not be unlocked by "normal" java-level locking and vice-versa. The specification - // doesn't specify what will occur if a program engages in such mixed-mode locking, however. - - enc_class Fast_Unlock( nabxRegP obj, eAXRegP box, eRegP tmp) %{ - - Register objReg = as_Register($obj$$reg); - Register boxReg = as_Register($box$$reg); - Register tmpReg = as_Register($tmp$$reg); - - guarantee (objReg != boxReg, "") ; - guarantee (objReg != tmpReg, "") ; - guarantee (boxReg != tmpReg, "") ; - guarantee (boxReg == as_Register(EAX_enc), "") ; - MacroAssembler masm(&cbuf); - - if (EmitSync & 4) { - // Disable - inhibit all inlining. Force control through the slow-path - masm.cmpptr (rsp, 0) ; - } else - if (EmitSync & 8) { - Label DONE_LABEL ; - if (UseBiasedLocking) { - masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); - } - // classic stack-locking code ... - masm.movptr(tmpReg, Address(boxReg, 0)) ; - masm.testptr(tmpReg, tmpReg) ; - masm.jcc (Assembler::zero, DONE_LABEL) ; - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses EAX which is box - masm.bind(DONE_LABEL); - } else { - Label DONE_LABEL, Stacked, CheckSucc, Inflated ; - - // Critically, the biased locking test must have precedence over - // and appear before the (box->dhw == 0) recursive stack-lock test. - if (UseBiasedLocking && !UseOptoBiasInlining) { - masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); - } - - masm.cmpptr(Address(boxReg, 0), 0) ; // Examine the displaced header - masm.movptr(tmpReg, Address(objReg, 0)) ; // Examine the object's markword - masm.jccb (Assembler::zero, DONE_LABEL) ; // 0 indicates recursive stack-lock - - masm.testptr(tmpReg, 0x02) ; // Inflated? - masm.jccb (Assembler::zero, Stacked) ; - - masm.bind (Inflated) ; - // It's inflated. - // Despite our balanced locking property we still check that m->_owner == Self - // as java routines or native JNI code called by this thread might - // have released the lock. - // Refer to the comments in synchronizer.cpp for how we might encode extra - // state in _succ so we can avoid fetching EntryList|cxq. - // - // I'd like to add more cases in fast_lock() and fast_unlock() -- - // such as recursive enter and exit -- but we have to be wary of - // I$ bloat, T$ effects and BP$ effects. - // - // If there's no contention try a 1-0 exit. That is, exit without - // a costly MEMBAR or CAS. See synchronizer.cpp for details on how - // we detect and recover from the race that the 1-0 exit admits. - // - // Conceptually Fast_Unlock() must execute a STST|LDST "release" barrier - // before it STs null into _owner, releasing the lock. Updates - // to data protected by the critical section must be visible before - // we drop the lock (and thus before any other thread could acquire - // the lock and observe the fields protected by the lock). - // IA32's memory-model is SPO, so STs are ordered with respect to - // each other and there's no need for an explicit barrier (fence). - // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. - - masm.get_thread (boxReg) ; - if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { - // prefetchw [ebx + Offset(_owner)-2] - masm.prefetchw(Address(rbx, ObjectMonitor::owner_offset_in_bytes()-2)); - } - - // Note that we could employ various encoding schemes to reduce - // the number of loads below (currently 4) to just 2 or 3. - // Refer to the comments in synchronizer.cpp. - // In practice the chain of fetches doesn't seem to impact performance, however. - if ((EmitSync & 65536) == 0 && (EmitSync & 256)) { - // Attempt to reduce branch density - AMD's branch predictor. - masm.xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; - masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; - masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; - masm.jccb (Assembler::notZero, DONE_LABEL) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; - masm.jmpb (DONE_LABEL) ; - } else { - masm.xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; - masm.jccb (Assembler::notZero, DONE_LABEL) ; - masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; - masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; - masm.jccb (Assembler::notZero, CheckSucc) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; - masm.jmpb (DONE_LABEL) ; - } - - // The Following code fragment (EmitSync & 65536) improves the performance of - // contended applications and contended synchronization microbenchmarks. - // Unfortunately the emission of the code - even though not executed - causes regressions - // in scimark and jetstream, evidently because of $ effects. Replacing the code - // with an equal number of never-executed NOPs results in the same regression. - // We leave it off by default. - - if ((EmitSync & 65536) != 0) { - Label LSuccess, LGoSlowPath ; - - masm.bind (CheckSucc) ; - - // Optional pre-test ... it's safe to elide this - if ((EmitSync & 16) == 0) { - masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0) ; - masm.jccb (Assembler::zero, LGoSlowPath) ; - } - - // We have a classic Dekker-style idiom: - // ST m->_owner = 0 ; MEMBAR; LD m->_succ - // There are a number of ways to implement the barrier: - // (1) lock:andl &m->_owner, 0 - // is fast, but mask doesn't currently support the "ANDL M,IMM32" form. - // LOCK: ANDL [ebx+Offset(_Owner)-2], 0 - // Encodes as 81 31 OFF32 IMM32 or 83 63 OFF8 IMM8 - // (2) If supported, an explicit MFENCE is appealing. - // In older IA32 processors MFENCE is slower than lock:add or xchg - // particularly if the write-buffer is full as might be the case if - // if stores closely precede the fence or fence-equivalent instruction. - // In more modern implementations MFENCE appears faster, however. - // (3) In lieu of an explicit fence, use lock:addl to the top-of-stack - // The $lines underlying the top-of-stack should be in M-state. - // The locked add instruction is serializing, of course. - // (4) Use xchg, which is serializing - // mov boxReg, 0; xchgl boxReg, [tmpReg + Offset(_owner)-2] also works - // (5) ST m->_owner = 0 and then execute lock:orl &m->_succ, 0. - // The integer condition codes will tell us if succ was 0. - // Since _succ and _owner should reside in the same $line and - // we just stored into _owner, it's likely that the $line - // remains in M-state for the lock:orl. - // - // We currently use (3), although it's likely that switching to (2) - // is correct for the future. - - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; - if (os::is_MP()) { - if (VM_Version::supports_sse2() && 1 == FenceInstruction) { - masm.mfence(); - } else { - masm.lock () ; masm.addptr(Address(rsp, 0), 0) ; - } - } - // Ratify _succ remains non-null - masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0) ; - masm.jccb (Assembler::notZero, LSuccess) ; - - masm.xorptr(boxReg, boxReg) ; // box is really EAX - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(rsp, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); - masm.jccb (Assembler::notEqual, LSuccess) ; - // Since we're low on registers we installed rsp as a placeholding in _owner. - // Now install Self over rsp. This is safe as we're transitioning from - // non-null to non=null - masm.get_thread (boxReg) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), boxReg) ; - // Intentional fall-through into LGoSlowPath ... - - masm.bind (LGoSlowPath) ; - masm.orptr(boxReg, 1) ; // set ICC.ZF=0 to indicate failure - masm.jmpb (DONE_LABEL) ; - - masm.bind (LSuccess) ; - masm.xorptr(boxReg, boxReg) ; // set ICC.ZF=1 to indicate success - masm.jmpb (DONE_LABEL) ; - } - - masm.bind (Stacked) ; - // It's not inflated and it's not recursively stack-locked and it's not biased. - // It must be stack-locked. - // Try to reset the header to displaced header. - // The "box" value on the stack is stable, so we can reload - // and be assured we observe the same value as above. - masm.movptr(tmpReg, Address(boxReg, 0)) ; - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses EAX which is box - // Intention fall-thru into DONE_LABEL - - - // DONE_LABEL is a hot target - we'd really like to place it at the - // start of cache line by padding with NOPs. - // See the AMD and Intel software optimization manuals for the - // most efficient "long" NOP encodings. - // Unfortunately none of our alignment mechanisms suffice. - if ((EmitSync & 65536) == 0) { - masm.bind (CheckSucc) ; - } - masm.bind(DONE_LABEL); - - // Avoid branch to branch on AMD processors - if (EmitSync & 32768) { masm.nop() ; } - } - %} - - enc_class enc_pop_rdx() %{ emit_opcode(cbuf,0x5A); %} @@ -13157,23 +12621,26 @@ instruct RethrowException() // inlined locking and unlocking - -instruct cmpFastLock( eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr) %{ - match( Set cr (FastLock object box) ); - effect( TEMP tmp, TEMP scr, USE_KILL box ); +instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr) %{ + match(Set cr (FastLock object box)); + effect(TEMP tmp, TEMP scr, USE_KILL box); ins_cost(300); format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr" %} - ins_encode( Fast_Lock(object,box,tmp,scr) ); - ins_pipe( pipe_slow ); + ins_encode %{ + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters); + %} + ins_pipe(pipe_slow); %} -instruct cmpFastUnlock( eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{ - match( Set cr (FastUnlock object box) ); - effect( TEMP tmp, USE_KILL box ); +instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{ + match(Set cr (FastUnlock object box)); + effect(TEMP tmp, USE_KILL box); ins_cost(300); format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %} - ins_encode( Fast_Unlock(object,box,tmp) ); - ins_pipe( pipe_slow ); + ins_encode %{ + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); + %} + ins_pipe(pipe_slow); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 21f9aca7619..2778320fdec 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -2599,231 +2599,6 @@ encode %{ %} - // obj: object to lock - // box: box address (header location) -- killed - // tmp: rax -- killed - // scr: rbx -- killed - // - // What follows is a direct transliteration of fast_lock() and fast_unlock() - // from i486.ad. See that file for comments. - // TODO: where possible switch from movq (r, 0) to movl(r,0) and - // use the shorter encoding. (Movl clears the high-order 32-bits). - - - enc_class Fast_Lock(rRegP obj, rRegP box, rax_RegI tmp, rRegP scr) - %{ - Register objReg = as_Register((int)$obj$$reg); - Register boxReg = as_Register((int)$box$$reg); - Register tmpReg = as_Register($tmp$$reg); - Register scrReg = as_Register($scr$$reg); - MacroAssembler masm(&cbuf); - - // Verify uniqueness of register assignments -- necessary but not sufficient - assert (objReg != boxReg && objReg != tmpReg && - objReg != scrReg && tmpReg != scrReg, "invariant") ; - - if (_counters != NULL) { - masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); - } - if (EmitSync & 1) { - // Without cast to int32_t a movptr will destroy r10 which is typically obj - masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; - masm.cmpptr(rsp, (int32_t)NULL_WORD) ; - } else - if (EmitSync & 2) { - Label DONE_LABEL; - if (UseBiasedLocking) { - // Note: tmpReg maps to the swap_reg argument and scrReg to the tmp_reg argument. - masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); - } - // QQQ was movl... - masm.movptr(tmpReg, 0x1); - masm.orptr(tmpReg, Address(objReg, 0)); - masm.movptr(Address(boxReg, 0), tmpReg); - if (os::is_MP()) { - masm.lock(); - } - masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg - masm.jcc(Assembler::equal, DONE_LABEL); - - // Recursive locking - masm.subptr(tmpReg, rsp); - masm.andptr(tmpReg, 7 - os::vm_page_size()); - masm.movptr(Address(boxReg, 0), tmpReg); - - masm.bind(DONE_LABEL); - masm.nop(); // avoid branch to branch - } else { - Label DONE_LABEL, IsInflated, Egress; - - masm.movptr(tmpReg, Address(objReg, 0)) ; - masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased - masm.jcc (Assembler::notZero, IsInflated) ; - - // it's stack-locked, biased or neutral - // TODO: optimize markword triage order to reduce the number of - // conditional branches in the most common cases. - // Beware -- there's a subtle invariant that fetch of the markword - // at [FETCH], below, will never observe a biased encoding (*101b). - // If this invariant is not held we'll suffer exclusion (safety) failure. - - if (UseBiasedLocking && !UseOptoBiasInlining) { - masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters); - masm.movptr(tmpReg, Address(objReg, 0)) ; // [FETCH] - } - - // was q will it destroy high? - masm.orl (tmpReg, 1) ; - masm.movptr(Address(boxReg, 0), tmpReg) ; - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg - if (_counters != NULL) { - masm.cond_inc32(Assembler::equal, - ExternalAddress((address) _counters->fast_path_entry_count_addr())); - } - masm.jcc (Assembler::equal, DONE_LABEL); - - // Recursive locking - masm.subptr(tmpReg, rsp); - masm.andptr(tmpReg, 7 - os::vm_page_size()); - masm.movptr(Address(boxReg, 0), tmpReg); - if (_counters != NULL) { - masm.cond_inc32(Assembler::equal, - ExternalAddress((address) _counters->fast_path_entry_count_addr())); - } - masm.jmp (DONE_LABEL) ; - - masm.bind (IsInflated) ; - // It's inflated - - // TODO: someday avoid the ST-before-CAS penalty by - // relocating (deferring) the following ST. - // We should also think about trying a CAS without having - // fetched _owner. If the CAS is successful we may - // avoid an RTO->RTS upgrade on the $line. - // Without cast to int32_t a movptr will destroy r10 which is typically obj - masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; - - masm.mov (boxReg, tmpReg) ; - masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.testptr(tmpReg, tmpReg) ; - masm.jcc (Assembler::notZero, DONE_LABEL) ; - - // It's inflated and appears unlocked - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - // Intentional fall-through into DONE_LABEL ... - - masm.bind (DONE_LABEL) ; - masm.nop () ; // avoid jmp to jmp - } - %} - - // obj: object to unlock - // box: box address (displaced header location), killed - // RBX: killed tmp; cannot be obj nor box - enc_class Fast_Unlock(rRegP obj, rax_RegP box, rRegP tmp) - %{ - - Register objReg = as_Register($obj$$reg); - Register boxReg = as_Register($box$$reg); - Register tmpReg = as_Register($tmp$$reg); - MacroAssembler masm(&cbuf); - - if (EmitSync & 4) { - masm.cmpptr(rsp, 0) ; - } else - if (EmitSync & 8) { - Label DONE_LABEL; - if (UseBiasedLocking) { - masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); - } - - // Check whether the displaced header is 0 - //(=> recursive unlock) - masm.movptr(tmpReg, Address(boxReg, 0)); - masm.testptr(tmpReg, tmpReg); - masm.jcc(Assembler::zero, DONE_LABEL); - - // If not recursive lock, reset the header to displaced header - if (os::is_MP()) { - masm.lock(); - } - masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box - masm.bind(DONE_LABEL); - masm.nop(); // avoid branch to branch - } else { - Label DONE_LABEL, Stacked, CheckSucc ; - - if (UseBiasedLocking && !UseOptoBiasInlining) { - masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); - } - - masm.movptr(tmpReg, Address(objReg, 0)) ; - masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ; - masm.jcc (Assembler::zero, DONE_LABEL) ; - masm.testl (tmpReg, 0x02) ; - masm.jcc (Assembler::zero, Stacked) ; - - // It's inflated - masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.xorptr(boxReg, r15_thread) ; - masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; - masm.jcc (Assembler::notZero, DONE_LABEL) ; - masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; - masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; - masm.jcc (Assembler::notZero, CheckSucc) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; - masm.jmp (DONE_LABEL) ; - - if ((EmitSync & 65536) == 0) { - Label LSuccess, LGoSlowPath ; - masm.bind (CheckSucc) ; - masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ; - masm.jcc (Assembler::zero, LGoSlowPath) ; - - // I'd much rather use lock:andl m->_owner, 0 as it's faster than the - // the explicit ST;MEMBAR combination, but masm doesn't currently support - // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc - // are all faster when the write buffer is populated. - masm.movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; - if (os::is_MP()) { - masm.lock () ; masm.addl (Address(rsp, 0), 0) ; - } - masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ; - masm.jcc (Assembler::notZero, LSuccess) ; - - masm.movptr (boxReg, (int32_t)NULL_WORD) ; // box is really EAX - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); - masm.jcc (Assembler::notEqual, LSuccess) ; - // Intentional fall-through into slow-path - - masm.bind (LGoSlowPath) ; - masm.orl (boxReg, 1) ; // set ICC.ZF=0 to indicate failure - masm.jmp (DONE_LABEL) ; - - masm.bind (LSuccess) ; - masm.testl (boxReg, 0) ; // set ICC.ZF=1 to indicate success - masm.jmp (DONE_LABEL) ; - } - - masm.bind (Stacked) ; - masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch - if (os::is_MP()) { masm.lock(); } - masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box - - if (EmitSync & 65536) { - masm.bind (CheckSucc) ; - } - masm.bind(DONE_LABEL); - if (EmitSync & 32768) { - masm.nop(); // avoid branch to branch - } - } - %} - - enc_class enc_rethrow() %{ cbuf.set_insts_mark(); @@ -11453,27 +11228,25 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{ // ============================================================================ // inlined locking and unlocking -instruct cmpFastLock(rFlagsReg cr, - rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) -%{ +instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{ match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box); - ins_cost(300); format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %} - ins_encode(Fast_Lock(object, box, tmp, scr)); + ins_encode %{ + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters); + %} ins_pipe(pipe_slow); %} -instruct cmpFastUnlock(rFlagsReg cr, - rRegP object, rax_RegP box, rRegP tmp) -%{ +instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{ match(Set cr (FastUnlock object box)); effect(TEMP tmp, USE_KILL box); - ins_cost(300); format %{ "fastunlock $object,$box\t! kills $box,$tmp" %} - ins_encode(Fast_Unlock(object, box, tmp)); + ins_encode %{ + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); + %} ins_pipe(pipe_slow); %} From 0b85ee832e4f48ecd5c05679780c36ad4f67bf5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rickard=20B=C3=A4ckman?= Date: Thu, 23 Jan 2014 12:08:28 +0100 Subject: [PATCH 102/265] 8027754: Enable loop optimizations for loops with MathExact inside Reviewed-by: kvn, iveresov --- hotspot/src/cpu/sparc/vm/sparc.ad | 13 - hotspot/src/cpu/x86/vm/x86_32.ad | 224 +++----- hotspot/src/cpu/x86/vm/x86_64.ad | 435 ++++++-------- hotspot/src/share/vm/adlc/archDesc.cpp | 15 +- hotspot/src/share/vm/opto/c2_globals.hpp | 2 +- hotspot/src/share/vm/opto/classes.hpp | 18 +- hotspot/src/share/vm/opto/compile.cpp | 36 -- hotspot/src/share/vm/opto/ifnode.cpp | 1 - hotspot/src/share/vm/opto/lcm.cpp | 7 - hotspot/src/share/vm/opto/library_call.cpp | 132 ++--- hotspot/src/share/vm/opto/loopTransform.cpp | 8 - hotspot/src/share/vm/opto/loopopts.cpp | 9 +- hotspot/src/share/vm/opto/matcher.cpp | 1 - hotspot/src/share/vm/opto/matcher.hpp | 4 - hotspot/src/share/vm/opto/mathexactnode.cpp | 537 ++++++------------ hotspot/src/share/vm/opto/mathexactnode.hpp | 205 +++---- hotspot/src/share/vm/opto/multnode.cpp | 5 - hotspot/src/share/vm/opto/node.hpp | 6 - hotspot/src/share/vm/opto/subnode.cpp | 6 +- hotspot/src/share/vm/opto/type.cpp | 4 + hotspot/src/share/vm/opto/type.hpp | 11 + hotspot/src/share/vm/runtime/vmStructs.cpp | 18 +- .../mathexact/AddExactICondTest.java | 2 +- .../mathexact/AddExactIConstantTest.java | 2 +- .../mathexact/AddExactILoadTest.java | 2 +- .../mathexact/AddExactILoopDependentTest.java | 2 +- .../mathexact/AddExactINonConstantTest.java | 2 +- .../mathexact/AddExactIRepeatTest.java | 2 +- .../mathexact/AddExactLConstantTest.java | 2 +- .../mathexact/AddExactLNonConstantTest.java | 2 +- .../intrinsics/mathexact/CompareTest.java | 2 +- .../intrinsics/mathexact/DecExactITest.java | 2 +- .../intrinsics/mathexact/DecExactLTest.java | 2 +- .../intrinsics/mathexact/GVNTest.java | 2 +- .../intrinsics/mathexact/IncExactITest.java | 2 +- .../intrinsics/mathexact/IncExactLTest.java | 2 +- .../mathexact/MulExactICondTest.java | 2 +- .../mathexact/MulExactIConstantTest.java | 2 +- .../mathexact/MulExactILoadTest.java | 2 +- .../mathexact/MulExactILoopDependentTest.java | 2 +- .../mathexact/MulExactINonConstantTest.java | 2 +- .../mathexact/MulExactIRepeatTest.java | 2 +- .../mathexact/MulExactLConstantTest.java | 2 +- .../mathexact/MulExactLNonConstantTest.java | 2 +- .../mathexact/NegExactIConstantTest.java | 2 +- .../mathexact/NegExactILoadTest.java | 6 +- .../mathexact/NegExactILoopDependentTest.java | 2 +- .../mathexact/NegExactINonConstantTest.java | 2 +- .../mathexact/NegExactLConstantTest.java | 2 +- .../mathexact/NegExactLNonConstantTest.java | 2 +- .../mathexact/NestedMathExactTest.java | 2 +- .../mathexact/SplitThruPhiTest.java | 2 +- .../mathexact/SubExactICondTest.java | 2 +- .../mathexact/SubExactIConstantTest.java | 2 +- .../mathexact/SubExactILoadTest.java | 2 +- .../mathexact/SubExactILoopDependentTest.java | 2 +- .../mathexact/SubExactINonConstantTest.java | 2 +- .../mathexact/SubExactIRepeatTest.java | 2 +- .../mathexact/SubExactLConstantTest.java | 2 +- .../mathexact/SubExactLNonConstantTest.java | 2 +- .../compiler/intrinsics/mathexact/Verify.java | 5 + .../mathexact/sanity/AddExactIntTest.java | 4 +- .../mathexact/sanity/AddExactLongTest.java | 4 +- .../sanity/DecrementExactIntTest.java | 4 +- .../sanity/DecrementExactLongTest.java | 6 +- .../sanity/IncrementExactIntTest.java | 4 +- .../sanity/IncrementExactLongTest.java | 4 +- .../sanity/MultiplyExactIntTest.java | 4 +- .../sanity/MultiplyExactLongTest.java | 4 +- .../mathexact/sanity/NegateExactIntTest.java | 4 +- .../mathexact/sanity/NegateExactLongTest.java | 4 +- .../sanity/SubtractExactIntTest.java | 4 +- .../sanity/SubtractExactLongTest.java | 4 +- 73 files changed, 675 insertions(+), 1157 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 3a470b0f851..15b5c7b524f 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -2037,19 +2037,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() { return L7_REGP_mask(); } -const RegMask Matcher::mathExactI_result_proj_mask() { - return G1_REGI_mask(); -} - -const RegMask Matcher::mathExactL_result_proj_mask() { - return G1_REGL_mask(); -} - -const RegMask Matcher::mathExactI_flags_proj_mask() { - return INT_FLAGS_mask(); -} - - %} diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index f13e5c17859..8948682a99f 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -1542,19 +1542,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() { return EBP_REG_mask(); } -const RegMask Matcher::mathExactI_result_proj_mask() { - return EAX_REG_mask(); -} - -const RegMask Matcher::mathExactL_result_proj_mask() { - ShouldNotReachHere(); - return RegMask(); -} - -const RegMask Matcher::mathExactI_flags_proj_mask() { - return INT_FLAGS_mask(); -} - // Returns true if the high 32 bits of the value is known to be zero. bool is_operand_hi32_zero(Node* n) { int opc = n->Opcode(); @@ -7009,44 +6996,6 @@ instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{ //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- -instruct addExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) -%{ - match(AddExactI dst src); - effect(DEF cr); - - format %{ "ADD $dst, $src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr) -%{ - match(AddExactI dst src); - effect(DEF cr); - - format %{ "ADD $dst, $src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) -%{ - match(AddExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(125); - format %{ "ADD $dst,$src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$Address); - %} - ins_pipe( ialu_reg_mem ); -%} - - // Integer Addition Instructions instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ match(Set dst (AddI dst src)); @@ -7356,43 +7305,6 @@ instruct xchgP( memory mem, pRegP newval) %{ //----------Subtraction Instructions------------------------------------------- -instruct subExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) -%{ - match(SubExactI dst src); - effect(DEF cr); - - format %{ "SUB $dst, $src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr) -%{ - match(SubExactI dst src); - effect(DEF cr); - - format %{ "SUB $dst, $src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) -%{ - match(SubExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(125); - format %{ "SUB $dst,$src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$Address); - %} - ins_pipe( ialu_reg_mem ); -%} - // Integer Subtraction Instructions instruct subI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ match(Set dst (SubI dst src)); @@ -7461,17 +7373,6 @@ instruct negI_eReg(rRegI dst, immI0 zero, eFlagsReg cr) %{ ins_pipe( ialu_reg ); %} -instruct negExactI_eReg(eAXRegI dst, eFlagsReg cr) %{ - match(NegExactI dst); - effect(DEF cr); - - format %{ "NEG $dst\t# negExact int"%} - ins_encode %{ - __ negl($dst$$Register); - %} - ins_pipe(ialu_reg); -%} - //----------Multiplication/Division Instructions------------------------------- // Integer Multiplication Instructions // Multiply Register @@ -7683,46 +7584,6 @@ instruct mulL_eReg_con(eADXRegL dst, immL_127 src, rRegI tmp, eFlagsReg cr) %{ ins_pipe( pipe_slow ); %} -instruct mulExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr) -%{ - match(MulExactI dst src); - effect(DEF cr); - - ins_cost(300); - format %{ "IMUL $dst, $src\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - -instruct mulExactI_eReg_imm(eAXRegI dst, rRegI src, immI imm, eFlagsReg cr) -%{ - match(MulExactI src imm); - effect(DEF cr); - - ins_cost(300); - format %{ "IMUL $dst, $src, $imm\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Register, $imm$$constant); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - -instruct mulExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr) -%{ - match(MulExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(350); - format %{ "IMUL $dst, $src\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Address); - %} - ins_pipe(ialu_reg_mem_alu0); -%} - - // Integer DIV with Register instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{ match(Set rax (DivI rax div)); @@ -8588,6 +8449,91 @@ instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, eFlagsReg cr) %{ instruct cadd_cmpLTMask_mem(ncxRegI p, ncxRegI q, memory y, eCXRegI tmp, eFlagsReg cr) %{ match(Set p (AddI (AndI (CmpLTMask p q) (LoadI y)) (SubI p q))); */ +//----------Overflow Math Instructions----------------------------------------- + +instruct overflowAddI_eReg(eFlagsReg cr, eAXRegI op1, rRegI op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "ADD $op1, $op2\t# overflow check int" %} + + ins_encode %{ + __ addl($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowAddI_rReg_imm(eFlagsReg cr, eAXRegI op1, immI op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "ADD $op1, $op2\t# overflow check int" %} + + ins_encode %{ + __ addl($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubI_rReg(eFlagsReg cr, rRegI op1, rRegI op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "CMP $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ cmpl($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "CMP $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ cmpl($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowNegI_rReg(eFlagsReg cr, immI0 zero, eAXRegI op2) +%{ + match(Set cr (OverflowSubI zero op2)); + effect(DEF cr, USE_KILL op2); + + format %{ "NEG $op2\t# overflow check int" %} + ins_encode %{ + __ negl($op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowMulI_rReg(eFlagsReg cr, eAXRegI op1, rRegI op2) +%{ + match(Set cr (OverflowMulI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "IMUL $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ imull($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg_alu0); +%} + +instruct overflowMulI_rReg_imm(eFlagsReg cr, rRegI op1, immI op2, rRegI tmp) +%{ + match(Set cr (OverflowMulI op1 op2)); + effect(DEF cr, TEMP tmp, USE op1, USE op2); + + format %{ "IMUL $tmp, $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ imull($tmp$$Register, $op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg_alu0); +%} //----------Long Instructions------------------------------------------------ // Add Long Register with Register diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 2778320fdec..b10f920793e 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -1657,18 +1657,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() { return PTR_RBP_REG_mask(); } -const RegMask Matcher::mathExactI_result_proj_mask() { - return INT_RAX_REG_mask(); -} - -const RegMask Matcher::mathExactL_result_proj_mask() { - return LONG_RAX_REG_mask(); -} - -const RegMask Matcher::mathExactI_flags_proj_mask() { - return INT_FLAGS_mask(); -} - %} //----------ENCODING BLOCK----------------------------------------------------- @@ -6738,82 +6726,6 @@ instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{ //----------Arithmetic Instructions-------------------------------------------- //----------Addition Instructions---------------------------------------------- -instruct addExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) -%{ - match(AddExactI dst src); - effect(DEF cr); - - format %{ "addl $dst, $src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr) -%{ - match(AddExactI dst src); - effect(DEF cr); - - format %{ "addl $dst, $src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) -%{ - match(AddExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(125); // XXX - format %{ "addl $dst, $src\t# addExact int" %} - ins_encode %{ - __ addl($dst$$Register, $src$$Address); - %} - - ins_pipe(ialu_reg_mem); -%} - -instruct addExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) -%{ - match(AddExactL dst src); - effect(DEF cr); - - format %{ "addq $dst, $src\t# addExact long" %} - ins_encode %{ - __ addq($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr) -%{ - match(AddExactL dst src); - effect(DEF cr); - - format %{ "addq $dst, $src\t# addExact long" %} - ins_encode %{ - __ addq($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct addExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr) -%{ - match(AddExactL dst (LoadL src)); - effect(DEF cr); - - ins_cost(125); // XXX - format %{ "addq $dst, $src\t# addExact long" %} - ins_encode %{ - __ addq($dst$$Register, $src$$Address); - %} - - ins_pipe(ialu_reg_mem); -%} - instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr) %{ match(Set dst (AddI dst src)); @@ -7426,80 +7338,6 @@ instruct subI_mem_imm(memory dst, immI src, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct subExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) -%{ - match(SubExactI dst src); - effect(DEF cr); - - format %{ "subl $dst, $src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr) -%{ - match(SubExactI dst src); - effect(DEF cr); - - format %{ "subl $dst, $src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) -%{ - match(SubExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(125); - format %{ "subl $dst, $src\t# subExact int" %} - ins_encode %{ - __ subl($dst$$Register, $src$$Address); - %} - ins_pipe(ialu_reg_mem); -%} - -instruct subExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) -%{ - match(SubExactL dst src); - effect(DEF cr); - - format %{ "subq $dst, $src\t# subExact long" %} - ins_encode %{ - __ subq($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr) -%{ - match(SubExactL dst (LoadL src)); - effect(DEF cr); - - format %{ "subq $dst, $src\t# subExact long" %} - ins_encode %{ - __ subq($dst$$Register, $src$$constant); - %} - ins_pipe(ialu_reg_reg); -%} - -instruct subExactL_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) -%{ - match(SubExactI dst src); - effect(DEF cr); - - ins_cost(125); - format %{ "subq $dst, $src\t# subExact long" %} - ins_encode %{ - __ subq($dst$$Register, $src$$Address); - %} - ins_pipe(ialu_reg_mem); -%} - instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr) %{ match(Set dst (SubL dst src)); @@ -7616,31 +7454,6 @@ instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr) ins_pipe(ialu_reg); %} -instruct negExactI_rReg(rax_RegI dst, rFlagsReg cr) -%{ - match(NegExactI dst); - effect(KILL cr); - - format %{ "negl $dst\t# negExact int" %} - ins_encode %{ - __ negl($dst$$Register); - %} - ins_pipe(ialu_reg); -%} - -instruct negExactL_rReg(rax_RegL dst, rFlagsReg cr) -%{ - match(NegExactL dst); - effect(KILL cr); - - format %{ "negq $dst\t# negExact long" %} - ins_encode %{ - __ negq($dst$$Register); - %} - ins_pipe(ialu_reg); -%} - - //----------Multiplication/Division Instructions------------------------------- // Integer Multiplication Instructions // Multiply Register @@ -7757,86 +7570,6 @@ instruct mulHiL_rReg(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr) ins_pipe(ialu_reg_reg_alu0); %} - -instruct mulExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) -%{ - match(MulExactI dst src); - effect(DEF cr); - - ins_cost(300); - format %{ "imull $dst, $src\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - - -instruct mulExactI_rReg_imm(rax_RegI dst, rRegI src, immI imm, rFlagsReg cr) -%{ - match(MulExactI src imm); - effect(DEF cr); - - ins_cost(300); - format %{ "imull $dst, $src, $imm\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Register, $imm$$constant); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - -instruct mulExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr) -%{ - match(MulExactI dst (LoadI src)); - effect(DEF cr); - - ins_cost(350); - format %{ "imull $dst, $src\t# mulExact int" %} - ins_encode %{ - __ imull($dst$$Register, $src$$Address); - %} - ins_pipe(ialu_reg_mem_alu0); -%} - -instruct mulExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr) -%{ - match(MulExactL dst src); - effect(DEF cr); - - ins_cost(300); - format %{ "imulq $dst, $src\t# mulExact long" %} - ins_encode %{ - __ imulq($dst$$Register, $src$$Register); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - -instruct mulExactL_rReg_imm(rax_RegL dst, rRegL src, immL32 imm, rFlagsReg cr) -%{ - match(MulExactL src imm); - effect(DEF cr); - - ins_cost(300); - format %{ "imulq $dst, $src, $imm\t# mulExact long" %} - ins_encode %{ - __ imulq($dst$$Register, $src$$Register, $imm$$constant); - %} - ins_pipe(ialu_reg_reg_alu0); -%} - -instruct mulExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr) -%{ - match(MulExactL dst (LoadL src)); - effect(DEF cr); - - ins_cost(350); - format %{ "imulq $dst, $src\t# mulExact long" %} - ins_encode %{ - __ imulq($dst$$Register, $src$$Address); - %} - ins_pipe(ialu_reg_mem_alu0); -%} - instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, rFlagsReg cr) %{ @@ -10445,6 +10178,174 @@ instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len, ins_pipe( pipe_slow ); %} +//----------Overflow Math Instructions----------------------------------------- + +instruct overflowAddI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "addl $op1, $op2\t# overflow check int" %} + + ins_encode %{ + __ addl($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowAddI_rReg_imm(rFlagsReg cr, rax_RegI op1, immI op2) +%{ + match(Set cr (OverflowAddI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "addl $op1, $op2\t# overflow check int" %} + + ins_encode %{ + __ addl($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowAddL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2) +%{ + match(Set cr (OverflowAddL op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "addq $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ addq($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowAddL_rReg_imm(rFlagsReg cr, rax_RegL op1, immL32 op2) +%{ + match(Set cr (OverflowAddL op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "addq $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ addq($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubI_rReg(rFlagsReg cr, rRegI op1, rRegI op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "cmpl $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ cmpl($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2) +%{ + match(Set cr (OverflowSubI op1 op2)); + + format %{ "cmpl $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ cmpl($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubL_rReg(rFlagsReg cr, rRegL op1, rRegL op2) +%{ + match(Set cr (OverflowSubL op1 op2)); + + format %{ "cmpq $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ cmpq($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowSubL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2) +%{ + match(Set cr (OverflowSubL op1 op2)); + + format %{ "cmpq $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ cmpq($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowNegI_rReg(rFlagsReg cr, immI0 zero, rax_RegI op2) +%{ + match(Set cr (OverflowSubI zero op2)); + effect(DEF cr, USE_KILL op2); + + format %{ "negl $op2\t# overflow check int" %} + ins_encode %{ + __ negl($op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowNegL_rReg(rFlagsReg cr, immL0 zero, rax_RegL op2) +%{ + match(Set cr (OverflowSubL zero op2)); + effect(DEF cr, USE_KILL op2); + + format %{ "negq $op2\t# overflow check long" %} + ins_encode %{ + __ negq($op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct overflowMulI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2) +%{ + match(Set cr (OverflowMulI op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "imull $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ imull($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg_alu0); +%} + +instruct overflowMulI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2, rRegI tmp) +%{ + match(Set cr (OverflowMulI op1 op2)); + effect(DEF cr, TEMP tmp, USE op1, USE op2); + + format %{ "imull $tmp, $op1, $op2\t# overflow check int" %} + ins_encode %{ + __ imull($tmp$$Register, $op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg_alu0); +%} + +instruct overflowMulL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2) +%{ + match(Set cr (OverflowMulL op1 op2)); + effect(DEF cr, USE_KILL op1, USE op2); + + format %{ "imulq $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ imulq($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg_alu0); +%} + +instruct overflowMulL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2, rRegL tmp) +%{ + match(Set cr (OverflowMulL op1 op2)); + effect(DEF cr, TEMP tmp, USE op1, USE op2); + + format %{ "imulq $tmp, $op1, $op2\t# overflow check long" %} + ins_encode %{ + __ imulq($tmp$$Register, $op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg_alu0); +%} + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions diff --git a/hotspot/src/share/vm/adlc/archDesc.cpp b/hotspot/src/share/vm/adlc/archDesc.cpp index 937f175117a..e577c0eead0 100644 --- a/hotspot/src/share/vm/adlc/archDesc.cpp +++ b/hotspot/src/share/vm/adlc/archDesc.cpp @@ -1167,15 +1167,12 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) { || strcmp(idealName,"CmpF") == 0 || strcmp(idealName,"FastLock") == 0 || strcmp(idealName,"FastUnlock") == 0 - || strcmp(idealName,"AddExactI") == 0 - || strcmp(idealName,"AddExactL") == 0 - || strcmp(idealName,"SubExactI") == 0 - || strcmp(idealName,"SubExactL") == 0 - || strcmp(idealName,"MulExactI") == 0 - || strcmp(idealName,"MulExactL") == 0 - || strcmp(idealName,"NegExactI") == 0 - || strcmp(idealName,"NegExactL") == 0 - || strcmp(idealName,"FlagsProj") == 0 + || strcmp(idealName,"OverflowAddI") == 0 + || strcmp(idealName,"OverflowAddL") == 0 + || strcmp(idealName,"OverflowSubI") == 0 + || strcmp(idealName,"OverflowSubL") == 0 + || strcmp(idealName,"OverflowMulI") == 0 + || strcmp(idealName,"OverflowMulL") == 0 || strcmp(idealName,"Bool") == 0 || strcmp(idealName,"Binary") == 0 ) { // Removed ConI from the must_clone list. CPUs that cannot use diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 2ccfb25517a..a22d6871ad6 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -644,7 +644,7 @@ diagnostic(bool, OptimizeExpensiveOps, true, \ "Find best control for expensive operations") \ \ - experimental(bool, UseMathExactIntrinsics, false, \ + product(bool, UseMathExactIntrinsics, true, \ "Enables intrinsification of various java.lang.Math functions") \ \ experimental(bool, ReplaceInParentMaps, false, \ diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index bbfd980dd76..3cdc2c58525 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -29,8 +29,6 @@ macro(AbsD) macro(AbsF) macro(AbsI) macro(AddD) -macro(AddExactI) -macro(AddExactL) macro(AddF) macro(AddI) macro(AddL) @@ -135,7 +133,6 @@ macro(EncodePKlass) macro(ExpD) macro(FastLock) macro(FastUnlock) -macro(FlagsProj) macro(Goto) macro(Halt) macro(If) @@ -170,9 +167,6 @@ macro(Loop) macro(LoopLimit) macro(Mach) macro(MachProj) -macro(MathExact) -macro(MathExactI) -macro(MathExactL) macro(MaxI) macro(MemBarAcquire) macro(LoadFence) @@ -194,22 +188,24 @@ macro(MoveF2I) macro(MoveL2D) macro(MoveD2L) macro(MulD) -macro(MulExactI) -macro(MulExactL) macro(MulF) macro(MulHiL) macro(MulI) macro(MulL) macro(Multi) macro(NegD) -macro(NegExactI) -macro(NegExactL) macro(NegF) macro(NeverBranch) macro(Opaque1) macro(Opaque2) macro(OrI) macro(OrL) +macro(OverflowAddI) +macro(OverflowSubI) +macro(OverflowMulI) +macro(OverflowAddL) +macro(OverflowSubL) +macro(OverflowMulL) macro(PCTable) macro(Parm) macro(PartialSubtypeCheck) @@ -253,8 +249,6 @@ macro(StrComp) macro(StrEquals) macro(StrIndexOf) macro(SubD) -macro(SubExactI) -macro(SubExactL) macro(SubF) macro(SubI) macro(SubL) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index d838a5b6a8c..f3b798296f4 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3028,42 +3028,6 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { n->set_req(MemBarNode::Precedent, top()); } break; - // Must set a control edge on all nodes that produce a FlagsProj - // so they can't escape the block that consumes the flags. - // Must also set the non throwing branch as the control - // for all nodes that depends on the result. Unless the node - // already have a control that isn't the control of the - // flag producer - case Op_FlagsProj: - { - MathExactNode* math = (MathExactNode*) n->in(0); - Node* ctrl = math->control_node(); - Node* non_throwing = math->non_throwing_branch(); - math->set_req(0, ctrl); - - Node* result = math->result_node(); - if (result != NULL) { - for (DUIterator_Fast jmax, j = result->fast_outs(jmax); j < jmax; j++) { - Node* out = result->fast_out(j); - // Phi nodes shouldn't be moved. They would only match below if they - // had the same control as the MathExactNode. The only time that - // would happen is if the Phi is also an input to the MathExact - // - // Cmp nodes shouldn't have control set at all. - if (out->is_Phi() || - out->is_Cmp()) { - continue; - } - - if (out->in(0) == NULL) { - out->set_req(0, non_throwing); - } else if (out->in(0) == ctrl) { - out->set_req(0, non_throwing); - } - } - } - } - break; default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" ); diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index 6e61a1f98bc..1c9dbb70839 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -76,7 +76,6 @@ static Node* split_if(IfNode *iff, PhaseIterGVN *igvn) { if( !i1->is_Bool() ) return NULL; BoolNode *b = i1->as_Bool(); Node *cmp = b->in(1); - if( cmp->is_FlagsProj() ) return NULL; if( !cmp->is_Cmp() ) return NULL; i1 = cmp->in(1); if( i1 == NULL || !i1->is_Phi() ) return NULL; diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 869928a54d9..8398bb3d254 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -520,13 +520,6 @@ Node* PhaseCFG::select(Block* block, Node_List &worklist, GrowableArray &re break; } - // For nodes that produce a FlagsProj, make the node adjacent to the - // use of the FlagsProj - if (use->is_FlagsProj() && get_block_for_node(use) == block) { - found_machif = true; - break; - } - // More than this instruction pending for successor to be ready, // don't choose this if other opportunities are ready if (ready_cnt.at(use->_idx) > 1) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 465de355b67..73c6e9090f9 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -203,7 +203,9 @@ class LibraryCallKit : public GraphKit { bool inline_math_native(vmIntrinsics::ID id); bool inline_trig(vmIntrinsics::ID id); bool inline_math(vmIntrinsics::ID id); - void inline_math_mathExact(Node* math); + template + bool inline_math_overflow(Node* arg1, Node* arg2); + void inline_math_mathExact(Node* math, Node* test); bool inline_math_addExactI(bool is_increment); bool inline_math_addExactL(bool is_increment); bool inline_math_multiplyExactI(); @@ -517,31 +519,31 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { case vmIntrinsics::_incrementExactI: case vmIntrinsics::_addExactI: - if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_incrementExactL: case vmIntrinsics::_addExactL: - if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_decrementExactI: case vmIntrinsics::_subtractExactI: - if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_decrementExactL: case vmIntrinsics::_subtractExactL: - if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_negateExactI: - if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_negateExactL: - if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_multiplyExactI: - if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL; break; case vmIntrinsics::_multiplyExactL: - if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL; + if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL; break; default: @@ -1970,18 +1972,8 @@ bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { return true; } -void LibraryCallKit::inline_math_mathExact(Node* math) { - // If we didn't get the expected opcode it means we have optimized - // the node to something else and don't need the exception edge. - if (!math->is_MathExact()) { - set_result(math); - return; - } - - Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node)); - Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node)); - - Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) ); +void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) { + Node* bol = _gvn.transform( new (C) BoolNode(test, BoolTest::overflow) ); IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); Node* fast_path = _gvn.transform( new (C) IfFalseNode(check)); Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) ); @@ -1999,108 +1991,50 @@ void LibraryCallKit::inline_math_mathExact(Node* math) { } set_control(fast_path); - set_result(result); + set_result(math); +} + +template +bool LibraryCallKit::inline_math_overflow(Node* arg1, Node* arg2) { + typedef typename OverflowOp::MathOp MathOp; + + MathOp* mathOp = new(C) MathOp(arg1, arg2); + Node* operation = _gvn.transform( mathOp ); + Node* ofcheck = _gvn.transform( new(C) OverflowOp(arg1, arg2) ); + inline_math_mathExact(operation, ofcheck); + return true; } bool LibraryCallKit::inline_math_addExactI(bool is_increment) { - Node* arg1 = argument(0); - Node* arg2 = NULL; - - if (is_increment) { - arg2 = intcon(1); - } else { - arg2 = argument(1); - } - - Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) ); - inline_math_mathExact(add); - return true; + return inline_math_overflow(argument(0), is_increment ? intcon(1) : argument(1)); } bool LibraryCallKit::inline_math_addExactL(bool is_increment) { - Node* arg1 = argument(0); // type long - // argument(1) == TOP - Node* arg2 = NULL; - - if (is_increment) { - arg2 = longcon(1); - } else { - arg2 = argument(2); // type long - // argument(3) == TOP - } - - Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2)); - inline_math_mathExact(add); - return true; + return inline_math_overflow(argument(0), is_increment ? longcon(1) : argument(2)); } bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) { - Node* arg1 = argument(0); - Node* arg2 = NULL; - - if (is_decrement) { - arg2 = intcon(1); - } else { - arg2 = argument(1); - } - - Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2)); - inline_math_mathExact(sub); - return true; + return inline_math_overflow(argument(0), is_decrement ? intcon(1) : argument(1)); } bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) { - Node* arg1 = argument(0); // type long - // argument(1) == TOP - Node* arg2 = NULL; - - if (is_decrement) { - arg2 = longcon(1); - } else { - arg2 = argument(2); // type long - // argument(3) == TOP - } - - Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2)); - inline_math_mathExact(sub); - return true; + return inline_math_overflow(argument(0), is_decrement ? longcon(1) : argument(2)); } bool LibraryCallKit::inline_math_negateExactI() { - Node* arg1 = argument(0); - - Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1)); - inline_math_mathExact(neg); - return true; + return inline_math_overflow(intcon(0), argument(0)); } bool LibraryCallKit::inline_math_negateExactL() { - Node* arg1 = argument(0); - // argument(1) == TOP - - Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1)); - inline_math_mathExact(neg); - return true; + return inline_math_overflow(longcon(0), argument(0)); } bool LibraryCallKit::inline_math_multiplyExactI() { - Node* arg1 = argument(0); - Node* arg2 = argument(1); - - Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2)); - inline_math_mathExact(mul); - return true; + return inline_math_overflow(argument(0), argument(1)); } bool LibraryCallKit::inline_math_multiplyExactL() { - Node* arg1 = argument(0); - // argument(1) == TOP - Node* arg2 = argument(2); - // argument(3) == TOP - - Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2)); - inline_math_mathExact(mul); - return true; + return inline_math_overflow(argument(0), argument(2)); } Node* diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 4cc7a537558..7fa685b03eb 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -713,10 +713,6 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const { case Op_ModL: body_size += 30; break; case Op_DivL: body_size += 30; break; case Op_MulL: body_size += 10; break; - case Op_FlagsProj: - // Can't handle unrolling of loops containing - // nodes that generate a FlagsProj at the moment - return false; case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: @@ -780,10 +776,6 @@ bool IdealLoopTree::policy_range_check( PhaseIdealLoop *phase ) const { continue; // not RC Node *cmp = bol->in(1); - if (cmp->is_FlagsProj()) { - continue; - } - Node *rc_exp = cmp->in(1); Node *limit = cmp->in(2); diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index ac97d3edec5..f9a87bbac57 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -43,12 +43,6 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { return NULL; } - if (n->is_MathExact()) { - // MathExact has projections that are not correctly handled in the code - // below. - return NULL; - } - int wins = 0; assert(!n->is_CFG(), ""); assert(region->is_Region(), ""); @@ -2362,8 +2356,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { opc == Op_Catch || opc == Op_CatchProj || opc == Op_Jump || - opc == Op_JumpProj || - opc == Op_FlagsProj) { + opc == Op_JumpProj) { #if !defined(PRODUCT) if (TracePartialPeeling) { tty->print_cr("\nExit control too complex: lp: %d", head->_idx); diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 6d35afde069..03ee1dc8086 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1998,7 +1998,6 @@ void Matcher::find_shared( Node *n ) { case Op_Catch: case Op_CatchProj: case Op_CProj: - case Op_FlagsProj: case Op_JumpProj: case Op_JProj: case Op_NeverBranch: diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index 6d0c8e3b050..38eeca40290 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -340,10 +340,6 @@ public: // Register for MODL projection of divmodL static RegMask modL_proj_mask(); - static const RegMask mathExactI_result_proj_mask(); - static const RegMask mathExactL_result_proj_mask(); - static const RegMask mathExactI_flags_proj_mask(); - // Use hardware DIV instruction when it is faster than // a code which use multiply for division by constant. static bool use_asm_for_ldiv_by_con( jlong divisor ); diff --git a/hotspot/src/share/vm/opto/mathexactnode.cpp b/hotspot/src/share/vm/opto/mathexactnode.cpp index bb930b37d52..00466ad3d50 100644 --- a/hotspot/src/share/vm/opto/mathexactnode.cpp +++ b/hotspot/src/share/vm/opto/mathexactnode.cpp @@ -31,358 +31,93 @@ #include "opto/mathexactnode.hpp" #include "opto/subnode.hpp" -MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) { - init_class_id(Class_MathExact); - init_req(0, ctrl); - init_req(1, in1); -} +template +class AddHelper { +public: + typedef typename OverflowOp::TypeClass TypeClass; + typedef typename TypeClass::NativeType NativeType; -MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) { - init_class_id(Class_MathExact); - init_req(0, ctrl); - init_req(1, in1); - init_req(2, in2); -} - -BoolNode* MathExactNode::bool_node() const { - Node* flags = flags_node(); - BoolNode* boolnode = flags->unique_out()->as_Bool(); - assert(boolnode != NULL, "must have BoolNode"); - return boolnode; -} - -IfNode* MathExactNode::if_node() const { - BoolNode* boolnode = bool_node(); - IfNode* ifnode = boolnode->unique_out()->as_If(); - assert(ifnode != NULL, "must have IfNode"); - return ifnode; -} - -Node* MathExactNode::control_node() const { - IfNode* ifnode = if_node(); - return ifnode->in(0); -} - -Node* MathExactNode::non_throwing_branch() const { - IfNode* ifnode = if_node(); - if (bool_node()->_test._test == BoolTest::overflow) { - return ifnode->proj_out(0); - } - return ifnode->proj_out(1); -} - -// If the MathExactNode won't overflow we have to replace the -// FlagsProjNode and ProjNode that is generated by the MathExactNode -Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) { - PhaseIterGVN* igvn = phase->is_IterGVN(); - if (igvn) { - ProjNode* result = result_node(); - ProjNode* flags = flags_node(); - - if (result != NULL) { - igvn->replace_node(result, new_result); - } - - if (flags != NULL) { - BoolNode* boolnode = bool_node(); - switch (boolnode->_test._test) { - case BoolTest::overflow: - // if the check is for overflow - never taken - igvn->replace_node(boolnode, phase->intcon(0)); - break; - case BoolTest::no_overflow: - // if the check is for no overflow - always taken - igvn->replace_node(boolnode, phase->intcon(1)); - break; - default: - fatal("Unexpected value of BoolTest"); - break; - } - flags->del_req(0); - } - } - return new_result; -} - -Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) { - uint ideal_reg = proj->ideal_reg(); - RegMask rm; - if (proj->_con == result_proj_node) { - rm = m->mathExactI_result_proj_mask(); - } else { - assert(proj->_con == flags_proj_node, "must be result or flags"); - assert(ideal_reg == Op_RegFlags, "sanity"); - rm = m->mathExactI_flags_proj_mask(); - } - return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); -} - -Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) { - uint ideal_reg = proj->ideal_reg(); - RegMask rm; - if (proj->_con == result_proj_node) { - rm = m->mathExactL_result_proj_mask(); - } else { - assert(proj->_con == flags_proj_node, "must be result or flags"); - assert(ideal_reg == Op_RegFlags, "sanity"); - rm = m->mathExactI_flags_proj_mask(); - } - return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); -} - -Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); - - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jint val1 = arg1->get_int(); - jint val2 = arg2->get_int(); - jint result = val1 + val2; + static bool will_overflow(NativeType value1, NativeType value2) { + NativeType result = value1 + value2; // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result - if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { - Node* con_result = ConINode::make(phase->C, result); - return no_overflow(phase, con_result); + if (((value1 ^ result) & (value2 ^ result)) >= 0) { + return false; } - return NULL; + return true; } - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x - Node* add_result = new (phase->C) AddINode(arg1, arg2); - return no_overflow(phase, add_result); - } - - if (type2->singleton()) { - return NULL; // no change - keep constant on the right - } - - if (type1->singleton()) { - // Make it x + Constant - move constant to the right - swap_edges(1, 2); - return this; - } - - if (arg2->is_Load()) { - return NULL; // no change - keep load on the right - } - - if (arg1->is_Load()) { - // Make it x + Load - move load to the right - swap_edges(1, 2); - return this; - } - - if (arg1->_idx > arg2->_idx) { - // Sort the edges - swap_edges(1, 2); - return this; - } - - return NULL; -} - -Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); - - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jlong val1 = arg1->get_long(); - jlong val2 = arg2->get_long(); - jlong result = val1 + val2; - // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result - if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { - Node* con_result = ConLNode::make(phase->C, result); - return no_overflow(phase, con_result); + static bool can_overflow(const Type* type1, const Type* type2) { + if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { + return false; } - return NULL; + return true; } +}; - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x - Node* add_result = new (phase->C) AddLNode(arg1, arg2); - return no_overflow(phase, add_result); - } +template +class SubHelper { +public: + typedef typename OverflowOp::TypeClass TypeClass; + typedef typename TypeClass::NativeType NativeType; - if (type2->singleton()) { - return NULL; // no change - keep constant on the right - } - - if (type1->singleton()) { - // Make it x + Constant - move constant to the right - swap_edges(1, 2); - return this; - } - - if (arg2->is_Load()) { - return NULL; // no change - keep load on the right - } - - if (arg1->is_Load()) { - // Make it x + Load - move load to the right - swap_edges(1, 2); - return this; - } - - if (arg1->_idx > arg2->_idx) { - // Sort the edges - swap_edges(1, 2); - return this; - } - - return NULL; -} - -Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); - - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jint val1 = arg1->get_int(); - jint val2 = arg2->get_int(); - jint result = val1 - val2; - - // Hacker's Delight 2-12 Overflow iff the arguments have different signs and + static bool will_overflow(NativeType value1, NativeType value2) { + NativeType result = value1 - value2; + // hacker's delight 2-12 overflow iff the arguments have different signs and // the sign of the result is different than the sign of arg1 - if (((val1 ^ val2) & (val1 ^ result)) >= 0) { - Node* con_result = ConINode::make(phase->C, result); - return no_overflow(phase, con_result); + if (((value1 ^ value2) & (value1 ^ result)) >= 0) { + return false; } - return NULL; + return true; } - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { - // Sub with zero is the same as add with zero - Node* add_result = new (phase->C) AddINode(arg1, arg2); - return no_overflow(phase, add_result); + static bool can_overflow(const Type* type1, const Type* type2) { + if (type2 == TypeClass::ZERO) { + return false; + } + return true; } +}; - return NULL; +template +class MulHelper { +public: + typedef typename OverflowOp::TypeClass TypeClass; + + static bool can_overflow(const Type* type1, const Type* type2) { + if (type1 == TypeClass::ZERO || type2 == TypeClass::ZERO) { + return false; + } else if (type1 == TypeClass::ONE || type2 == TypeClass::ONE) { + return false; + } + return true; + } +}; + +bool OverflowAddINode::will_overflow(jint v1, jint v2) const { + return AddHelper::will_overflow(v1, v2); } -Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); - - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jlong val1 = arg1->get_long(); - jlong val2 = arg2->get_long(); - jlong result = val1 - val2; - - // Hacker's Delight 2-12 Overflow iff the arguments have different signs and - // the sign of the result is different than the sign of arg1 - if (((val1 ^ val2) & (val1 ^ result)) >= 0) { - Node* con_result = ConLNode::make(phase->C, result); - return no_overflow(phase, con_result); - } - return NULL; - } - - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { - // Sub with zero is the same as add with zero - Node* add_result = new (phase->C) AddLNode(arg1, arg2); - return no_overflow(phase, add_result); - } - - return NULL; +bool OverflowSubINode::will_overflow(jint v1, jint v2) const { + return SubHelper::will_overflow(v1, v2); } -Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node *arg = in(1); - - const Type* type = phase->type(arg); - if (type != Type::TOP && type->singleton()) { - jint value = arg->get_int(); - if (value != min_jint) { - Node* neg_result = ConINode::make(phase->C, -value); - return no_overflow(phase, neg_result); - } - } - return NULL; -} - -Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node *arg = in(1); - - const Type* type = phase->type(arg); - if (type != Type::TOP && type->singleton()) { - jlong value = arg->get_long(); - if (value != min_jlong) { - Node* neg_result = ConLNode::make(phase->C, -value); - return no_overflow(phase, neg_result); - } - } - return NULL; -} - -Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); - - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jint val1 = arg1->get_int(); - jint val2 = arg2->get_int(); - jlong result = (jlong) val1 * (jlong) val2; +bool OverflowMulINode::will_overflow(jint v1, jint v2) const { + jlong result = (jlong) v1 * (jlong) v2; if ((jint) result == result) { - // no overflow - Node* mul_result = ConINode::make(phase->C, result); - return no_overflow(phase, mul_result); + return false; } - } - - if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { - return no_overflow(phase, ConINode::make(phase->C, 0)); - } - - if (type1 == TypeInt::ONE) { - Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0)); - return no_overflow(phase, mul_result); - } - if (type2 == TypeInt::ONE) { - Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0)); - return no_overflow(phase, mul_result); - } - - if (type1 == TypeInt::MINUS_1) { - return new (phase->C) NegExactINode(NULL, arg2); - } - - if (type2 == TypeInt::MINUS_1) { - return new (phase->C) NegExactINode(NULL, arg1); - } - - return NULL; + return true; } -Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { - Node* arg1 = in(1); - Node* arg2 = in(2); +bool OverflowAddLNode::will_overflow(jlong v1, jlong v2) const { + return AddHelper::will_overflow(v1, v2); +} - const Type* type1 = phase->type(arg1); - const Type* type2 = phase->type(arg2); - - if (type1 != Type::TOP && type1->singleton() && - type2 != Type::TOP && type2->singleton()) { - jlong val1 = arg1->get_long(); - jlong val2 = arg2->get_long(); +bool OverflowSubLNode::will_overflow(jlong v1, jlong v2) const { + return SubHelper::will_overflow(v1, v2); +} +bool OverflowMulLNode::will_overflow(jlong val1, jlong val2) const { jlong result = val1 * val2; jlong ax = (val1 < 0 ? -val1 : val1); jlong ay = (val2 < 0 ? -val2 : val2); @@ -398,33 +133,125 @@ Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { } } - if (!overflow) { - Node* mul_result = ConLNode::make(phase->C, result); - return no_overflow(phase, mul_result); - } - } - - if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { - return no_overflow(phase, ConLNode::make(phase->C, 0)); - } - - if (type1 == TypeLong::ONE) { - Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0)); - return no_overflow(phase, mul_result); - } - if (type2 == TypeLong::ONE) { - Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0)); - return no_overflow(phase, mul_result); - } - - if (type1 == TypeLong::MINUS_1) { - return new (phase->C) NegExactLNode(NULL, arg2); - } - - if (type2 == TypeLong::MINUS_1) { - return new (phase->C) NegExactLNode(NULL, arg1); - } - - return NULL; + return overflow; +} + +bool OverflowAddINode::can_overflow(const Type* t1, const Type* t2) const { + return AddHelper::can_overflow(t1, t2); +} + +bool OverflowSubINode::can_overflow(const Type* t1, const Type* t2) const { + if (in(1) == in(2)) { + return false; + } + return SubHelper::can_overflow(t1, t2); +} + +bool OverflowMulINode::can_overflow(const Type* t1, const Type* t2) const { + return MulHelper::can_overflow(t1, t2); +} + +bool OverflowAddLNode::can_overflow(const Type* t1, const Type* t2) const { + return AddHelper::can_overflow(t1, t2); +} + +bool OverflowSubLNode::can_overflow(const Type* t1, const Type* t2) const { + if (in(1) == in(2)) { + return false; + } + return SubHelper::can_overflow(t1, t2); +} + +bool OverflowMulLNode::can_overflow(const Type* t1, const Type* t2) const { + return MulHelper::can_overflow(t1, t2); +} + +const Type* OverflowNode::sub(const Type* t1, const Type* t2) const { + fatal(err_msg_res("sub() should not be called for '%s'", NodeClassNames[this->Opcode()])); + return TypeInt::CC; +} + +template +struct IdealHelper { + typedef typename OverflowOp::TypeClass TypeClass; // TypeInt, TypeLong + typedef typename TypeClass::NativeType NativeType; + + static Node* Ideal(const OverflowOp* node, PhaseGVN* phase, bool can_reshape) { + Node* arg1 = node->in(1); + Node* arg2 = node->in(2); + const Type* type1 = phase->type(arg1); + const Type* type2 = phase->type(arg2); + + if (type1 == NULL || type2 == NULL) { + return NULL; + } + + if (type1 != Type::TOP && type1->singleton() && + type2 != Type::TOP && type2->singleton()) { + NativeType val1 = TypeClass::as_self(type1)->get_con(); + NativeType val2 = TypeClass::as_self(type2)->get_con(); + if (node->will_overflow(val1, val2) == false) { + Node* con_result = ConINode::make(phase->C, 0); + return con_result; + } + return NULL; + } + return NULL; + } + + static const Type* Value(const OverflowOp* node, PhaseTransform* phase) { + const Type *t1 = phase->type( node->in(1) ); + const Type *t2 = phase->type( node->in(2) ); + if( t1 == Type::TOP ) return Type::TOP; + if( t2 == Type::TOP ) return Type::TOP; + + const TypeClass* i1 = TypeClass::as_self(t1); + const TypeClass* i2 = TypeClass::as_self(t2); + + if (i1 == NULL || i2 == NULL) { + return TypeInt::CC; + } + + if (t1->singleton() && t2->singleton()) { + NativeType val1 = i1->get_con(); + NativeType val2 = i2->get_con(); + if (node->will_overflow(val1, val2)) { + return TypeInt::CC; + } + return TypeInt::ZERO; + } else if (i1 != TypeClass::TYPE_DOMAIN && i2 != TypeClass::TYPE_DOMAIN) { + if (node->will_overflow(i1->_lo, i2->_lo)) { + return TypeInt::CC; + } else if (node->will_overflow(i1->_lo, i2->_hi)) { + return TypeInt::CC; + } else if (node->will_overflow(i1->_hi, i2->_lo)) { + return TypeInt::CC; + } else if (node->will_overflow(i1->_hi, i2->_hi)) { + return TypeInt::CC; + } + return TypeInt::ZERO; + } + + if (!node->can_overflow(t1, t2)) { + return TypeInt::ZERO; + } + return TypeInt::CC; + } +}; + +Node* OverflowINode::Ideal(PhaseGVN* phase, bool can_reshape) { + return IdealHelper::Ideal(this, phase, can_reshape); +} + +Node* OverflowLNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return IdealHelper::Ideal(this, phase, can_reshape); +} + +const Type* OverflowINode::Value(PhaseTransform* phase) const { + return IdealHelper::Value(this, phase); +} + +const Type* OverflowLNode::Value(PhaseTransform* phase) const { + return IdealHelper::Value(this, phase); } diff --git a/hotspot/src/share/vm/opto/mathexactnode.hpp b/hotspot/src/share/vm/opto/mathexactnode.hpp index a30304ba93a..3e037cf568b 100644 --- a/hotspot/src/share/vm/opto/mathexactnode.hpp +++ b/hotspot/src/share/vm/opto/mathexactnode.hpp @@ -27,128 +27,111 @@ #include "opto/multnode.hpp" #include "opto/node.hpp" +#include "opto/addnode.hpp" #include "opto/subnode.hpp" #include "opto/type.hpp" -class BoolNode; -class IfNode; -class Node; - class PhaseGVN; class PhaseTransform; -class MathExactNode : public MultiNode { +class OverflowNode : public CmpNode { public: - MathExactNode(Node* ctrl, Node* in1); - MathExactNode(Node* ctrl, Node* in1, Node* in2); - enum { - result_proj_node = 0, - flags_proj_node = 1 - }; - virtual int Opcode() const; - virtual Node* Identity(PhaseTransform* phase) { return this; } - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; } - virtual const Type* Value(PhaseTransform* phase) const { return bottom_type(); } - virtual uint hash() const { return NO_HASH; } - virtual bool is_CFG() const { return false; } - virtual uint ideal_reg() const { return NotAMachineReg; } + OverflowNode(Node* in1, Node* in2) : CmpNode(in1, in2) {} - ProjNode* result_node() const { return proj_out(result_proj_node); } - ProjNode* flags_node() const { return proj_out(flags_proj_node); } - Node* control_node() const; - Node* non_throwing_branch() const; -protected: - IfNode* if_node() const; - BoolNode* bool_node() const; - Node* no_overflow(PhaseGVN *phase, Node* new_result); -}; - -class MathExactINode : public MathExactNode { - public: - MathExactINode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {} - MathExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* match(const ProjNode* proj, const Matcher* m); - virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; } -}; - -class MathExactLNode : public MathExactNode { -public: - MathExactLNode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {} - MathExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* match(const ProjNode* proj, const Matcher* m); - virtual const Type* bottom_type() const { return TypeTuple::LONG_CC_PAIR; } -}; - -class AddExactINode : public MathExactINode { -public: - AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); -}; - -class AddExactLNode : public MathExactLNode { -public: - AddExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class SubExactINode : public MathExactINode { -public: - SubExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class SubExactLNode : public MathExactLNode { -public: - SubExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class NegExactINode : public MathExactINode { -public: - NegExactINode(Node* ctrl, Node* in1) : MathExactINode(ctrl, in1) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class NegExactLNode : public MathExactLNode { -public: - NegExactLNode(Node* ctrl, Node* in1) : MathExactLNode(ctrl, in1) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class MulExactINode : public MathExactINode { -public: - MulExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class MulExactLNode : public MathExactLNode { -public: - MulExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {} - virtual int Opcode() const; - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); -}; - -class FlagsProjNode : public ProjNode { -public: - FlagsProjNode(Node* src, uint con) : ProjNode(src, con) { - init_class_id(Class_FlagsProj); - } - - virtual int Opcode() const; - virtual bool is_CFG() const { return false; } - virtual const Type* bottom_type() const { return TypeInt::CC; } virtual uint ideal_reg() const { return Op_RegFlags; } + virtual const Type* sub(const Type* t1, const Type* t2) const; }; +class OverflowINode : public OverflowNode { +public: + typedef TypeInt TypeClass; + + OverflowINode(Node* in1, Node* in2) : OverflowNode(in1, in2) {} + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual const Type* Value(PhaseTransform* phase) const; + + virtual bool will_overflow(jint v1, jint v2) const = 0; + virtual bool can_overflow(const Type* t1, const Type* t2) const = 0; +}; + + +class OverflowLNode : public OverflowNode { +public: + typedef TypeLong TypeClass; + + OverflowLNode(Node* in1, Node* in2) : OverflowNode(in1, in2) {} + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual const Type* Value(PhaseTransform* phase) const; + + virtual bool will_overflow(jlong v1, jlong v2) const = 0; + virtual bool can_overflow(const Type* t1, const Type* t2) const = 0; +}; + +class OverflowAddINode : public OverflowINode { +public: + typedef AddINode MathOp; + + OverflowAddINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jint v1, jint v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; + +class OverflowSubINode : public OverflowINode { +public: + typedef SubINode MathOp; + + OverflowSubINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jint v1, jint v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; + +class OverflowMulINode : public OverflowINode { +public: + typedef MulINode MathOp; + + OverflowMulINode(Node* in1, Node* in2) : OverflowINode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jint v1, jint v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; + +class OverflowAddLNode : public OverflowLNode { +public: + typedef AddLNode MathOp; + + OverflowAddLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jlong v1, jlong v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; + +class OverflowSubLNode : public OverflowLNode { +public: + typedef SubLNode MathOp; + + OverflowSubLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jlong v1, jlong v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; + +class OverflowMulLNode : public OverflowLNode { +public: + typedef MulLNode MathOp; + + OverflowMulLNode(Node* in1, Node* in2) : OverflowLNode(in1, in2) {} + virtual int Opcode() const; + + virtual bool will_overflow(jlong v1, jlong v2) const; + virtual bool can_overflow(const Type* t1, const Type* t2) const; +}; #endif diff --git a/hotspot/src/share/vm/opto/multnode.cpp b/hotspot/src/share/vm/opto/multnode.cpp index d9e04a2741d..300f6246369 100644 --- a/hotspot/src/share/vm/opto/multnode.cpp +++ b/hotspot/src/share/vm/opto/multnode.cpp @@ -54,11 +54,6 @@ ProjNode* MultiNode::proj_out(uint which_proj) const { assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); return proj; } - } else if (p->is_FlagsProj()) { - FlagsProjNode *proj = p->as_FlagsProj(); - if (proj->_con == which_proj) { - return proj; - } } else { assert(p == this && this->is_Start(), "else must be proj"); continue; diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index b04a0fad78e..5f883d5f1cf 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -69,7 +69,6 @@ class EncodePNode; class EncodePKlassNode; class FastLockNode; class FastUnlockNode; -class FlagsProjNode; class IfNode; class IfFalseNode; class IfTrueNode; @@ -100,7 +99,6 @@ class MachSafePointNode; class MachSpillCopyNode; class MachTempNode; class Matcher; -class MathExactNode; class MemBarNode; class MemBarStoreStoreNode; class MemNode; @@ -575,7 +573,6 @@ public: DEFINE_CLASS_ID(MemBar, Multi, 3) DEFINE_CLASS_ID(Initialize, MemBar, 0) DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1) - DEFINE_CLASS_ID(MathExact, Multi, 4) DEFINE_CLASS_ID(Mach, Node, 1) DEFINE_CLASS_ID(MachReturn, Mach, 0) @@ -632,7 +629,6 @@ public: DEFINE_CLASS_ID(Cmp, Sub, 0) DEFINE_CLASS_ID(FastLock, Cmp, 0) DEFINE_CLASS_ID(FastUnlock, Cmp, 1) - DEFINE_CLASS_ID(FlagsProj, Cmp, 2) DEFINE_CLASS_ID(MergeMem, Node, 7) DEFINE_CLASS_ID(Bool, Node, 8) @@ -736,7 +732,6 @@ public: DEFINE_CLASS_QUERY(EncodePKlass) DEFINE_CLASS_QUERY(FastLock) DEFINE_CLASS_QUERY(FastUnlock) - DEFINE_CLASS_QUERY(FlagsProj) DEFINE_CLASS_QUERY(If) DEFINE_CLASS_QUERY(IfFalse) DEFINE_CLASS_QUERY(IfTrue) @@ -765,7 +760,6 @@ public: DEFINE_CLASS_QUERY(MachSafePoint) DEFINE_CLASS_QUERY(MachSpillCopy) DEFINE_CLASS_QUERY(MachTemp) - DEFINE_CLASS_QUERY(MathExact) DEFINE_CLASS_QUERY(Mem) DEFINE_CLASS_QUERY(MemBar) DEFINE_CLASS_QUERY(MemBarStoreStore) diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index fcbead264af..71ffed86691 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.cpp @@ -1126,11 +1126,15 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *cmp = in(1); if( !cmp->is_Sub() ) return NULL; int cop = cmp->Opcode(); - if( cop == Op_FastLock || cop == Op_FastUnlock || cop == Op_FlagsProj) return NULL; + if( cop == Op_FastLock || cop == Op_FastUnlock) return NULL; Node *cmp1 = cmp->in(1); Node *cmp2 = cmp->in(2); if( !cmp1 ) return NULL; + if (_test._test == BoolTest::overflow || _test._test == BoolTest::no_overflow) { + return NULL; + } + // Constant on left? Node *con = cmp1; uint op2 = cmp2->Opcode(); diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index c907fc7124c..b957a227eb6 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -306,6 +306,7 @@ void Type::Initialize_shared(Compile* current) { TypeInt::POS1 = TypeInt::make(1,max_jint, WidenMin); // Positive values TypeInt::INT = TypeInt::make(min_jint,max_jint, WidenMax); // 32-bit integers TypeInt::SYMINT = TypeInt::make(-max_jint,max_jint,WidenMin); // symmetric range + TypeInt::TYPE_DOMAIN = TypeInt::INT; // CmpL is overloaded both as the bytecode computation returning // a trinary (-1,0,+1) integer result AND as an efficient long // compare returning optimizer ideal-type flags. @@ -322,6 +323,7 @@ void Type::Initialize_shared(Compile* current) { TypeLong::LONG = TypeLong::make(min_jlong,max_jlong,WidenMax); // 64-bit integers TypeLong::INT = TypeLong::make((jlong)min_jint,(jlong)max_jint,WidenMin); TypeLong::UINT = TypeLong::make(0,(jlong)max_juint,WidenMin); + TypeLong::TYPE_DOMAIN = TypeLong::LONG; const Type **fboth =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*)); fboth[0] = Type::CONTROL; @@ -1161,6 +1163,7 @@ const TypeInt *TypeInt::POS; // Positive 32-bit integers or zero const TypeInt *TypeInt::POS1; // Positive 32-bit integers const TypeInt *TypeInt::INT; // 32-bit integers const TypeInt *TypeInt::SYMINT; // symmetric range [-max_jint..max_jint] +const TypeInt *TypeInt::TYPE_DOMAIN; // alias for TypeInt::INT //------------------------------TypeInt---------------------------------------- TypeInt::TypeInt( jint lo, jint hi, int w ) : Type(Int), _lo(lo), _hi(hi), _widen(w) { @@ -1418,6 +1421,7 @@ const TypeLong *TypeLong::POS; // >=0 const TypeLong *TypeLong::LONG; // 64-bit integers const TypeLong *TypeLong::INT; // 32-bit subrange const TypeLong *TypeLong::UINT; // 32-bit unsigned subrange +const TypeLong *TypeLong::TYPE_DOMAIN; // alias for TypeLong::LONG //------------------------------TypeLong--------------------------------------- TypeLong::TypeLong( jlong lo, jlong hi, int w ) : Type(Long), _lo(lo), _hi(hi), _widen(w) { diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index d02792f7bb3..8c30f69795e 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -489,6 +489,7 @@ protected: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: + typedef jint NativeType; virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -531,6 +532,9 @@ public: static const TypeInt *POS1; static const TypeInt *INT; static const TypeInt *SYMINT; // symmetric range [-max_jint..max_jint] + static const TypeInt *TYPE_DOMAIN; // alias for TypeInt::INT + + static const TypeInt *as_self(const Type *t) { return t->is_int(); } #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const; #endif @@ -546,6 +550,7 @@ protected: // Do not kill _widen bits. virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: + typedef jlong NativeType; virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -568,6 +573,7 @@ public: virtual bool is_finite() const; // Has a finite value + virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. virtual const Type *widen( const Type *t, const Type* limit_type ) const; @@ -580,6 +586,11 @@ public: static const TypeLong *LONG; static const TypeLong *INT; // 32-bit subrange [min_jint..max_jint] static const TypeLong *UINT; // 32-bit unsigned [0..max_juint] + static const TypeLong *TYPE_DOMAIN; // alias for TypeLong::LONG + + // static convenience methods. + static const TypeLong *as_self(const Type *t) { return t->is_long(); } + #ifndef PRODUCT virtual void dump2( Dict &d, uint, outputStream *st ) const;// Specialized per-Type dumping #endif diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 32ae760a129..0fd2d70881f 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1942,15 +1942,6 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; declare_c2_type(CmpF3Node, CmpFNode) \ declare_c2_type(CmpDNode, CmpNode) \ declare_c2_type(CmpD3Node, CmpDNode) \ - declare_c2_type(MathExactNode, MultiNode) \ - declare_c2_type(MathExactINode, MathExactNode) \ - declare_c2_type(AddExactINode, MathExactINode) \ - declare_c2_type(AddExactLNode, MathExactLNode) \ - declare_c2_type(SubExactINode, MathExactINode) \ - declare_c2_type(SubExactLNode, MathExactLNode) \ - declare_c2_type(NegExactINode, MathExactINode) \ - declare_c2_type(MulExactINode, MathExactINode) \ - declare_c2_type(FlagsProjNode, ProjNode) \ declare_c2_type(BoolNode, Node) \ declare_c2_type(AbsNode, Node) \ declare_c2_type(AbsINode, AbsNode) \ @@ -2031,6 +2022,15 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; declare_c2_type(ExtractLNode, ExtractNode) \ declare_c2_type(ExtractFNode, ExtractNode) \ declare_c2_type(ExtractDNode, ExtractNode) \ + declare_c2_type(OverflowNode, CmpNode) \ + declare_c2_type(OverflowINode, OverflowNode) \ + declare_c2_type(OverflowAddINode, OverflowINode) \ + declare_c2_type(OverflowSubINode, OverflowINode) \ + declare_c2_type(OverflowMulINode, OverflowINode) \ + declare_c2_type(OverflowLNode, OverflowNode) \ + declare_c2_type(OverflowAddLNode, OverflowLNode) \ + declare_c2_type(OverflowSubLNode, OverflowLNode) \ + declare_c2_type(OverflowMulLNode, OverflowLNode) \ \ /*********************/ \ /* Adapter Blob Entries */ \ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java index f0835cdb197..8862160d8b4 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java @@ -26,7 +26,7 @@ * @bug 8024924 * @summary Test non constant addExact * @compile AddExactICondTest.java - * @run main AddExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactICondTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java index ed8525483b0..77000a1d958 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java @@ -26,7 +26,7 @@ * @bug 8024924 * @summary Test constant addExact * @compile AddExactIConstantTest.java Verify.java - * @run main AddExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactIConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java index 4175a8ab5cc..2d96bb8b8a6 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java @@ -26,7 +26,7 @@ * @bug 8024924 * @summary Test non constant addExact * @compile AddExactILoadTest.java Verify.java - * @run main AddExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactILoadTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java index 56da9f40b7e..99aae0d7b21 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java @@ -26,7 +26,7 @@ * @bug 8024924 * @summary Test non constant addExact * @compile AddExactILoopDependentTest.java Verify.java - * @run main AddExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactILoopDependentTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java index 52e208db0e4..b3a24758569 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8024924 * @summary Test non constant addExact * @compile AddExactINonConstantTest.java Verify.java - * @run main AddExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactINonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java index 7bb1deba007..d111b66ce82 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java @@ -26,7 +26,7 @@ * @bug 8025657 * @summary Test repeating addExact * @compile AddExactIRepeatTest.java Verify.java - * @run main AddExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactIRepeatTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java index 3514ce24ab7..dc751406192 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant addExact * @compile AddExactLConstantTest.java Verify.java - * @run main AddExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactLConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java index 3e16cb94d95..efd5fd7c92b 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant addExact * @compile AddExactLNonConstantTest.java Verify.java - * @run main AddExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main AddExactLNonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/CompareTest.java b/hotspot/test/compiler/intrinsics/mathexact/CompareTest.java index c77dd47c184..f6785c07c69 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/CompareTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/CompareTest.java @@ -26,7 +26,7 @@ * @bug 8026722 * @summary Verify that the compare after addExact is a signed compare * @compile CompareTest.java - * @run main CompareTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main CompareTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java b/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java index 2712bed78ab..7e6e1ca3bde 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test decrementExact * @compile DecExactITest.java Verify.java - * @run main DecExactITest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main DecExactITest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java b/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java index ad83dcad208..53a16596e3c 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test decrementExact * @compile DecExactLTest.java Verify.java - * @run main DecExactLTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main DecExactLTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/GVNTest.java b/hotspot/test/compiler/intrinsics/mathexact/GVNTest.java index 864555e2b3e..23fba15d433 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/GVNTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/GVNTest.java @@ -26,7 +26,7 @@ * @bug 8028207 * @summary Verify that GVN doesn't mess up the two addExacts * @compile GVNTest.java - * @run main GVNTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main GVNTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java b/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java index 41ab825847a..9f7ddbd3211 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test incrementExact * @compile IncExactITest.java Verify.java - * @run main IncExactITest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main IncExactITest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java b/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java index 6ece9792be7..755d81908ce 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test incrementExact * @compile IncExactLTest.java Verify.java - * @run main IncExactLTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main IncExactLTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java index e9bf6b9958e..5f3e1e64568 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test multiplyExact as condition * @compile MulExactICondTest.java - * @run main MulExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactICondTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java index 6bb74d1f9eb..120bef5e9b9 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant multiplyExact * @compile MulExactIConstantTest.java Verify.java - * @run main MulExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactIConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java index 8878b6f1c6d..36aa3d46230 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test multiplyExact * @compile MulExactILoadTest.java Verify.java - * @run main MulExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactILoadTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java index 7c5c7e7a240..5ba4ad3cfc3 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test loop dependent multiplyExact * @compile MulExactILoopDependentTest.java Verify.java - * @run main MulExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactILoopDependentTest * */ public class MulExactILoopDependentTest { diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java index e924311aa25..e108059885b 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant multiplyExact * @compile MulExactINonConstantTest.java Verify.java - * @run main MulExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactINonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java index 5d5a93d05d7..dd14ce21ed6 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test repeating multiplyExact * @compile MulExactIRepeatTest.java Verify.java - * @run main MulExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactIRepeatTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java index 9668ddfe07e..c687cc276f2 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant mulExact * @compile MulExactLConstantTest.java Verify.java - * @run main MulExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactLConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java index 3486588c81e..f9d82ed0876 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant mulExact * @compile MulExactLNonConstantTest.java Verify.java - * @run main MulExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main MulExactLNonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java index 0a5e164ba68..ba49d778762 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant negExact * @compile NegExactIConstantTest.java Verify.java - * @run main NegExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactIConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java index e7896835ee1..d7e8215600a 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java @@ -26,14 +26,14 @@ * @bug 8026844 * @summary Test negExact * @compile NegExactILoadTest.java Verify.java - * @run main NegExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactILoadTest * */ public class NegExactILoadTest { public static void main(String[] args) { - Verify.LoadTest.init(); - Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI())); + Verify.LoadTest.init(); + Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI())); } } diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java index a18b0c17eed..882f80b91a1 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test negExact loop dependent * @compile NegExactILoopDependentTest.java Verify.java - * @run main NegExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactILoopDependentTest * */ public class NegExactILoopDependentTest { diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java index ee87bd82748..6f044f0d969 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant negExact * @compile NegExactINonConstantTest.java Verify.java - * @run main NegExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactINonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java index 82e02a960a9..382cd5c5f9e 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant negExact * @compile NegExactLConstantTest.java Verify.java - * @run main NegExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactLConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java index b7b967dc28e..0bcad8b2b78 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant negExact * @compile NegExactLNonConstantTest.java Verify.java - * @run main NegExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NegExactLNonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/NestedMathExactTest.java b/hotspot/test/compiler/intrinsics/mathexact/NestedMathExactTest.java index 883fcceacaa..211dc8baff1 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/NestedMathExactTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/NestedMathExactTest.java @@ -26,7 +26,7 @@ * @bug 8027444 * @summary Test nested loops * @compile NestedMathExactTest.java - * @run main NestedMathExactTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main NestedMathExactTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java b/hotspot/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java index 67f3afab007..b3b0c0d7417 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java @@ -26,7 +26,7 @@ * @bug 8028198 * @summary Verify that split through phi does the right thing * @compile SplitThruPhiTest.java - * @run main SplitThruPhiTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SplitThruPhiTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java index b4dd4f7daa9..f539bdc7cbe 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test subtractExact as condition * @compile SubExactICondTest.java Verify.java - * @run main SubExactICondTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactICondTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java index 20a27cef161..b450bd90b11 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test constant subtractExact * @compile SubExactIConstantTest.java Verify.java - * @run main SubExactIConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactIConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java index 5be582fd03a..af2ed018258 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant subtractExact * @compile SubExactILoadTest.java Verify.java - * @run main SubExactILoadTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactILoadTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java index b4e7b4a30a8..67ebcbca321 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant subtractExact * @compile SubExactILoopDependentTest.java Verify.java - * @run main SubExactILoopDependentTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactILoopDependentTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java index 82dc81c3d00..b8153810892 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test non constant subtractExact * @compile SubExactINonConstantTest.java Verify.java - * @run main SubExactINonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactINonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java index 63e4b3d1876..3c57f6f3f76 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java @@ -26,7 +26,7 @@ * @bug 8026844 * @summary Test repeating subtractExact * @compile SubExactIRepeatTest.java Verify.java - * @run main SubExactIRepeatTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactIRepeatTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java index 973aa6a3960..ec554d7662b 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java @@ -27,7 +27,7 @@ * @bug 8027353 * @summary Test constant subtractExact * @compile SubExactLConstantTest.java Verify.java - * @run main SubExactLConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactLConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java b/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java index bc0c7331b76..86ecf20f366 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java @@ -27,7 +27,7 @@ * @bug 8027353 * @summary Test non constant subtractExact * @compile SubExactLNonConstantTest.java Verify.java - * @run main SubExactLNonConstantTest -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseMathExactIntrinsics + * @run main SubExactLNonConstantTest * */ diff --git a/hotspot/test/compiler/intrinsics/mathexact/Verify.java b/hotspot/test/compiler/intrinsics/mathexact/Verify.java index a4d728bfd6b..3936bf1b4f4 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/Verify.java +++ b/hotspot/test/compiler/intrinsics/mathexact/Verify.java @@ -160,6 +160,7 @@ public class Verify { public static class NonConstantTest { public static java.util.Random rnd = new java.util.Random(); + public static int[] values = new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE }; public static void verify(BinaryMethod method) { for (int i = 0; i < 50000; ++i) { @@ -169,6 +170,10 @@ public class Verify { Verify.verifyBinary(rnd1 + 1, rnd2, method); Verify.verifyBinary(rnd1 - 1, rnd2, method); Verify.verifyBinary(rnd1, rnd2 - 1, method); + Verify.verifyBinary(0, values[0], method); + Verify.verifyBinary(values[0], 0, method); + Verify.verifyBinary(0, values[1], method); + Verify.verifyBinary(values[1], 0, method); } } } diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java index c55f847d2a2..a2770dcddf3 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build AddExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics AddExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java index 4823f073f5f..c5756440769 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build AddExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics AddExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics AddExactLongTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java index 0b97ab86ae6..19641a1f41a 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build DecrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics DecrementExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java index f2429aa9142..a5821698f9d 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build DecrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics DecrementExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics DecrementExactLongTest @@ -42,4 +42,4 @@ public class DecrementExactLongTest { public static void main(String[] args) throws Exception { new IntrinsicBase.LongTest(MathIntrinsic.LongIntrinsic.Decrement).test(); } -} \ No newline at end of file +} diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java index 714f4e2e04e..bca840ad8f1 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build IncrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics IncrementExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java index 19511c49929..5348b774f9b 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build IncrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics IncrementExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics IncrementExactLongTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java index bd433500187..a09c1244905 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build MultiplyExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics MultiplyExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java index 70651107dae..23154e9ecef 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build MultiplyExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics MultiplyExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics MultiplyExactLongTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java index 579c2907e91..f41bb7995a9 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build NegateExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics NegateExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java index 6f114f632ab..27af6553036 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build NegateExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics NegateExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics NegateExactLongTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java index d1eaf3919d5..c2cbbc4ef95 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build SubtractExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics SubtractExactIntTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactIntTest diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java index fbe8eb1e12e..bee6d3bafc4 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java @@ -26,11 +26,11 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build SubtractExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs_neg.log -XX:-UseMathExactIntrinsics SubtractExactLongTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod * -XX:LogFile=hs.log -XX:+UseMathExactIntrinsics SubtractExactLongTest From c19a7e0fa3df91f1122b45e2b602e5ea5226842f Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 24 Jan 2014 09:31:53 +0100 Subject: [PATCH 103/265] 8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed Type methods shouldn't always operate on speculative part Reviewed-by: kvn, twisti --- hotspot/src/share/vm/opto/callGenerator.cpp | 4 +- hotspot/src/share/vm/opto/cfgnode.cpp | 8 +- hotspot/src/share/vm/opto/compile.cpp | 41 ++++-- hotspot/src/share/vm/opto/connode.cpp | 8 +- hotspot/src/share/vm/opto/connode.hpp | 2 +- hotspot/src/share/vm/opto/graphKit.cpp | 8 +- hotspot/src/share/vm/opto/loopopts.cpp | 8 +- hotspot/src/share/vm/opto/memnode.cpp | 4 +- hotspot/src/share/vm/opto/multnode.cpp | 2 +- hotspot/src/share/vm/opto/node.cpp | 4 +- hotspot/src/share/vm/opto/parse1.cpp | 4 +- hotspot/src/share/vm/opto/parse2.cpp | 10 +- hotspot/src/share/vm/opto/parse3.cpp | 2 +- hotspot/src/share/vm/opto/phaseX.cpp | 23 +++- hotspot/src/share/vm/opto/phaseX.hpp | 6 +- hotspot/src/share/vm/opto/type.cpp | 125 +++++++++++------- hotspot/src/share/vm/opto/type.hpp | 89 +++++++++---- .../TestSpeculationFailedHigherEqual.java | 63 +++++++++ 18 files changed, 290 insertions(+), 121 deletions(-) create mode 100644 hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 6e9c98d3436..a509f01994e 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -722,7 +722,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) Node* m = kit.map()->in(i); Node* n = slow_map->in(i); if (m != n) { - const Type* t = gvn.type(m)->meet(gvn.type(n)); + const Type* t = gvn.type(m)->meet_speculative(gvn.type(n)); Node* phi = PhiNode::make(region, m, t); phi->set_req(2, n); kit.map()->set_req(i, gvn.transform(phi)); @@ -975,7 +975,7 @@ JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_pa Node* m = kit.map()->in(i); Node* n = slow_map->in(i); if (m != n) { - const Type* t = gvn.type(m)->meet(gvn.type(n)); + const Type* t = gvn.type(m)->meet_speculative(gvn.type(n)); Node* phi = PhiNode::make(region, m, t); phi->set_req(2, n); kit.map()->set_req(i, gvn.transform(phi)); diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 36818b75b13..25223035f29 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -951,7 +951,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { if (is_intf != ti_is_intf) { t = _type; break; } } - t = t->meet(ti); + t = t->meet_speculative(ti); } } @@ -968,11 +968,11 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // // It is not possible to see Type::BOTTOM values as phi inputs, // because the ciTypeFlow pre-pass produces verifier-quality types. - const Type* ft = t->filter(_type); // Worst case type + const Type* ft = t->filter_speculative(_type); // Worst case type #ifdef ASSERT // The following logic has been moved into TypeOopPtr::filter. - const Type* jt = t->join(_type); + const Type* jt = t->join_speculative(_type); if( jt->empty() ) { // Emptied out??? // Check for evil case of 't' being a class and '_type' expecting an @@ -1757,7 +1757,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { break; } // Accumulate type for resulting Phi - type = type->meet(in(i)->in(AddPNode::Base)->bottom_type()); + type = type->meet_speculative(in(i)->in(AddPNode::Base)->bottom_type()); } Node* base = NULL; if (doit) { diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index ba8debaaeea..80acf7f317c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3919,16 +3919,18 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) { // which may optimize it out. for (uint next = 0; next < worklist.size(); ++next) { Node *n = worklist.at(next); - if (n->is_Type() && n->as_Type()->type()->isa_oopptr() != NULL && - n->as_Type()->type()->is_oopptr()->speculative() != NULL) { + if (n->is_Type()) { TypeNode* tn = n->as_Type(); - const TypeOopPtr* t = tn->type()->is_oopptr(); - bool in_hash = igvn.hash_delete(n); - assert(in_hash, "node should be in igvn hash table"); - tn->set_type(t->remove_speculative()); - igvn.hash_insert(n); - igvn._worklist.push(n); // give it a chance to go away - modified++; + const Type* t = tn->type(); + const Type* t_no_spec = t->remove_speculative(); + if (t_no_spec != t) { + bool in_hash = igvn.hash_delete(n); + assert(in_hash, "node should be in igvn hash table"); + tn->set_type(t_no_spec); + igvn.hash_insert(n); + igvn._worklist.push(n); // give it a chance to go away + modified++; + } } uint max = n->len(); for( uint i = 0; i < max; ++i ) { @@ -3942,6 +3944,27 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) { if (modified > 0) { igvn.optimize(); } +#ifdef ASSERT + // Verify that after the IGVN is over no speculative type has resurfaced + worklist.clear(); + worklist.push(root()); + for (uint next = 0; next < worklist.size(); ++next) { + Node *n = worklist.at(next); + const Type* t = igvn.type(n); + assert(t == t->remove_speculative(), "no more speculative types"); + if (n->is_Type()) { + t = n->as_Type()->type(); + assert(t == t->remove_speculative(), "no more speculative types"); + } + uint max = n->len(); + for( uint i = 0; i < max; ++i ) { + Node *m = n->in(i); + if (not_a_node(m)) continue; + worklist.push(m); + } + } + igvn.check_no_speculative_types(); +#endif } } diff --git a/hotspot/src/share/vm/opto/connode.cpp b/hotspot/src/share/vm/opto/connode.cpp index 948ff7b4632..0a71bc598e4 100644 --- a/hotspot/src/share/vm/opto/connode.cpp +++ b/hotspot/src/share/vm/opto/connode.cpp @@ -188,7 +188,7 @@ Node *CMoveNode::Identity( PhaseTransform *phase ) { const Type *CMoveNode::Value( PhaseTransform *phase ) const { if( phase->type(in(Condition)) == Type::TOP ) return Type::TOP; - return phase->type(in(IfFalse))->meet(phase->type(in(IfTrue))); + return phase->type(in(IfFalse))->meet_speculative(phase->type(in(IfTrue))); } //------------------------------make------------------------------------------- @@ -392,14 +392,14 @@ Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) { //============================================================================= // If input is already higher or equal to cast type, then this is an identity. Node *ConstraintCastNode::Identity( PhaseTransform *phase ) { - return phase->type(in(1))->higher_equal(_type) ? in(1) : this; + return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this; } //------------------------------Value------------------------------------------ // Take 'join' of input and cast-up type const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const { if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP; - const Type* ft = phase->type(in(1))->filter(_type); +const Type* ft = phase->type(in(1))->filter_speculative(_type); #ifdef ASSERT // Previous versions of this function had some special case logic, @@ -409,7 +409,7 @@ const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const { { const Type* t1 = phase->type(in(1)); if( t1 == Type::TOP ) assert(ft == Type::TOP, "special case #1"); - const Type* rt = t1->join(_type); + const Type* rt = t1->join_speculative(_type); if (rt->empty()) assert(ft == Type::TOP, "special case #2"); break; } diff --git a/hotspot/src/share/vm/opto/connode.hpp b/hotspot/src/share/vm/opto/connode.hpp index 53ff820d8d5..03a096b2331 100644 --- a/hotspot/src/share/vm/opto/connode.hpp +++ b/hotspot/src/share/vm/opto/connode.hpp @@ -36,7 +36,7 @@ class MachNode; // Simple constants class ConNode : public TypeNode { public: - ConNode( const Type *t ) : TypeNode(t,1) { + ConNode( const Type *t ) : TypeNode(t->remove_speculative(),1) { init_req(0, (Node*)Compile::current()->root()); init_flags(Flag_is_Con); } diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index c30cdc12c82..e7ec989c5fe 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -420,7 +420,7 @@ void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* ph } const Type* srctype = _gvn.type(src); if (phi->type() != srctype) { - const Type* dsttype = phi->type()->meet(srctype); + const Type* dsttype = phi->type()->meet_speculative(srctype); if (phi->type() != dsttype) { phi->set_type(dsttype); _gvn.set_type(phi, dsttype); @@ -1223,7 +1223,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // See if mixing in the NULL pointer changes type. // If so, then the NULL pointer was not allowed in the original // type. In other words, "value" was not-null. - if (t->meet(TypePtr::NULL_PTR) != t) { + if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) { // same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ... explicit_null_checks_elided++; return value; // Elided null check quickly! @@ -1356,7 +1356,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // Cast obj to not-null on this path Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) { const Type *t = _gvn.type(obj); - const Type *t_not_null = t->join(TypePtr::NOTNULL); + const Type *t_not_null = t->join_speculative(TypePtr::NOTNULL); // Object is already not-null? if( t == t_not_null ) return obj; @@ -3009,7 +3009,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, if (failure_control != NULL) // failure is now impossible (*failure_control) = top(); // adjust the type of the phi to the exact klass: - phi->raise_bottom_type(_gvn.type(cast_obj)->meet(TypePtr::NULL_PTR)); + phi->raise_bottom_type(_gvn.type(cast_obj)->meet_speculative(TypePtr::NULL_PTR)); } } diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index ba19f7493cc..ac97d3edec5 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -1115,8 +1115,8 @@ BoolNode *PhaseIdealLoop::clone_iff( PhiNode *phi, IdealLoopTree *loop ) { Node *n2 = phi->in(i)->in(1)->in(2); phi1->set_req( i, n1 ); phi2->set_req( i, n2 ); - phi1->set_type( phi1->type()->meet(n1->bottom_type()) ); - phi2->set_type( phi2->type()->meet(n2->bottom_type()) ); + phi1->set_type( phi1->type()->meet_speculative(n1->bottom_type())); + phi2->set_type( phi2->type()->meet_speculative(n2->bottom_type())); } // See if these Phis have been made before. // Register with optimizer @@ -1189,8 +1189,8 @@ CmpNode *PhaseIdealLoop::clone_bool( PhiNode *phi, IdealLoopTree *loop ) { } phi1->set_req( j, n1 ); phi2->set_req( j, n2 ); - phi1->set_type( phi1->type()->meet(n1->bottom_type()) ); - phi2->set_type( phi2->type()->meet(n2->bottom_type()) ); + phi1->set_type(phi1->type()->meet_speculative(n1->bottom_type())); + phi2->set_type(phi2->type()->meet_speculative(n2->bottom_type())); } // See if these Phis have been made before. diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 14d347b8e69..9e712dc6730 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -657,7 +657,7 @@ const TypePtr* MemNode::calculate_adr_type(const Type* t, const TypePtr* cross_c // disregarding "null"-ness. // (We make an exception for TypeRawPtr::BOTTOM, which is a bit bucket.) const TypePtr* tp_notnull = tp->join(TypePtr::NOTNULL)->is_ptr(); - assert(cross_check->meet(tp_notnull) == cross_check, + assert(cross_check->meet(tp_notnull) == cross_check->remove_speculative(), "real address must not escape from expected memory type"); } #endif @@ -1681,7 +1681,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // t might actually be lower than _type, if _type is a unique // concrete subclass of abstract class t. if (off_beyond_header) { // is the offset beyond the header? - const Type* jt = t->join(_type); + const Type* jt = t->join_speculative(_type); // In any case, do not allow the join, per se, to empty out the type. if (jt->empty() && !t->empty()) { // This can happen if a interface-typed array narrows to a class type. diff --git a/hotspot/src/share/vm/opto/multnode.cpp b/hotspot/src/share/vm/opto/multnode.cpp index 106a0086c63..d9e04a2741d 100644 --- a/hotspot/src/share/vm/opto/multnode.cpp +++ b/hotspot/src/share/vm/opto/multnode.cpp @@ -94,7 +94,7 @@ const Type* ProjNode::proj_type(const Type* t) const { if ((_con == TypeFunc::Parms) && n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method()) { // The result of autoboxing is always non-null on normal path. - t = t->join(TypePtr::NOTNULL); + t = t->join_speculative(TypePtr::NOTNULL); } return t; } diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 06e74b6d0f2..d3ee58a4b1e 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -995,13 +995,13 @@ void Node::raise_bottom_type(const Type* new_type) { if (is_Type()) { TypeNode *n = this->as_Type(); if (VerifyAliases) { - assert(new_type->higher_equal(n->type()), "new type must refine old type"); + assert(new_type->higher_equal_speculative(n->type()), "new type must refine old type"); } n->set_type(new_type); } else if (is_Load()) { LoadNode *n = this->as_Load(); if (VerifyAliases) { - assert(new_type->higher_equal(n->type()), "new type must refine old type"); + assert(new_type->higher_equal_speculative(n->type()), "new type must refine old type"); } n->set_type(new_type); } diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index de7188ff871..747c78e399a 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -1649,7 +1649,7 @@ void Parse::merge_common(Parse::Block* target, int pnum) { assert(bt1 != Type::BOTTOM, "should not be building conflict phis"); map()->set_req(j, _gvn.transform_no_reclaim(phi)); debug_only(const Type* bt2 = phi->bottom_type()); - assert(bt2->higher_equal(bt1), "must be consistent with type-flow"); + assert(bt2->higher_equal_speculative(bt1), "must be consistent with type-flow"); record_for_igvn(phi); } } @@ -2022,7 +2022,7 @@ void Parse::return_current(Node* value) { !tp->klass()->is_interface()) { // sharpen the type eagerly; this eases certain assert checking if (tp->higher_equal(TypeInstPtr::NOTNULL)) - tr = tr->join(TypeInstPtr::NOTNULL)->is_instptr(); + tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr(); value = _gvn.transform(new (C) CheckCastPPNode(0,value,tr)); } } diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 75746213087..543539902e8 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -88,7 +88,7 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { if (toop->klass()->as_instance_klass()->unique_concrete_subklass()) { // If we load from "AbstractClass[]" we must see "ConcreteSubClass". const Type* subklass = Type::get_const_type(toop->klass()); - elemtype = subklass->join(el); + elemtype = subklass->join_speculative(el); } } } @@ -1278,7 +1278,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest, // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) // or the narrowOop equivalent. const Type* obj_type = _gvn.type(obj); - const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr(); + const TypeOopPtr* tboth = obj_type->join_speculative(con_type)->isa_oopptr(); if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type && tboth->higher_equal(obj_type)) { // obj has to be of the exact type Foo if the CmpP succeeds. @@ -1288,7 +1288,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest, (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth); const Type* tcc = ccast->as_Type()->type(); - assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); + assert(tcc != obj_type && tcc->higher_equal_speculative(obj_type), "must improve"); // Delay transform() call to allow recovery of pre-cast value // at the control merge. _gvn.set_type_bottom(ccast); @@ -1318,7 +1318,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest, switch (btest) { case BoolTest::eq: // Constant test? { - const Type* tboth = tcon->join(tval); + const Type* tboth = tcon->join_speculative(tval); if (tboth == tval) break; // Nothing to gain. if (tcon->isa_int()) { ccast = new (C) CastIINode(val, tboth); @@ -1352,7 +1352,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest, if (ccast != NULL) { const Type* tcc = ccast->as_Type()->type(); - assert(tcc != tval && tcc->higher_equal(tval), "must improve"); + assert(tcc != tval && tcc->higher_equal_speculative(tval), "must improve"); // Delay transform() call to allow recovery of pre-cast value // at the control merge. ccast->set_req(0, control()); diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 8c545f3ece5..a72fb7e5401 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -337,7 +337,7 @@ bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_au // should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2) // An oop is not scavengable if it is in the perm gen. if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr()) - con_type = con_type->join(stable_type); + con_type = con_type->join_speculative(stable_type); break; case T_ILLEGAL: diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 3e6ab4eafff..fd08b065c5f 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -323,6 +323,23 @@ void NodeHash::remove_useless_nodes(VectorSet &useful) { } } + +void NodeHash::check_no_speculative_types() { +#ifdef ASSERT + uint max = size(); + Node *sentinel_node = sentinel(); + for (uint i = 0; i < max; ++i) { + Node *n = at(i); + if(n != NULL && n != sentinel_node && n->is_Type()) { + TypeNode* tn = n->as_Type(); + const Type* t = tn->type(); + const Type* t_no_spec = t->remove_speculative(); + assert(t == t_no_spec, "dead node in hash table or missed node during speculative cleanup"); + } + } +#endif +} + #ifndef PRODUCT //------------------------------dump------------------------------------------- // Dump statistics for the hash table @@ -1392,11 +1409,11 @@ void PhaseIterGVN::remove_speculative_types() { assert(UseTypeSpeculation, "speculation is off"); for (uint i = 0; i < _types.Size(); i++) { const Type* t = _types.fast_lookup(i); - if (t != NULL && t->isa_oopptr()) { - const TypeOopPtr* to = t->is_oopptr(); - _types.map(i, to->remove_speculative()); + if (t != NULL) { + _types.map(i, t->remove_speculative()); } } + _table.check_no_speculative_types(); } //============================================================================= diff --git a/hotspot/src/share/vm/opto/phaseX.hpp b/hotspot/src/share/vm/opto/phaseX.hpp index d03d47d95bc..fcdd47ee852 100644 --- a/hotspot/src/share/vm/opto/phaseX.hpp +++ b/hotspot/src/share/vm/opto/phaseX.hpp @@ -92,7 +92,8 @@ public: } void remove_useless_nodes(VectorSet &useful); // replace with sentinel - void replace_with(NodeHash* nh); + void replace_with(NodeHash* nh); + void check_no_speculative_types(); // Check no speculative part for type nodes in table Node *sentinel() { return _sentinel; } @@ -501,6 +502,9 @@ public: Deoptimization::DeoptReason reason); void remove_speculative_types(); + void check_no_speculative_types() { + _table.check_no_speculative_types(); + } #ifndef PRODUCT protected: diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 83806a3235b..181e69aca27 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -236,6 +236,13 @@ int Type::cmp( const Type *const t1, const Type *const t2 ) { return !t1->eq(t2); // Return ZERO if equal } +const Type* Type::maybe_remove_speculative(bool include_speculative) const { + if (!include_speculative) { + return remove_speculative(); + } + return this; +} + //------------------------------hash------------------------------------------- int Type::uhash( const Type *const t ) { return t->hash(); @@ -628,41 +635,44 @@ bool Type::interface_vs_oop(const Type *t) const { //------------------------------meet------------------------------------------- // Compute the MEET of two types. NOT virtual. It enforces that meet is // commutative and the lattice is symmetric. -const Type *Type::meet( const Type *t ) const { +const Type *Type::meet_helper(const Type *t, bool include_speculative) const { if (isa_narrowoop() && t->isa_narrowoop()) { - const Type* result = make_ptr()->meet(t->make_ptr()); + const Type* result = make_ptr()->meet_helper(t->make_ptr(), include_speculative); return result->make_narrowoop(); } if (isa_narrowklass() && t->isa_narrowklass()) { - const Type* result = make_ptr()->meet(t->make_ptr()); + const Type* result = make_ptr()->meet_helper(t->make_ptr(), include_speculative); return result->make_narrowklass(); } - const Type *mt = xmeet(t); + const Type *this_t = maybe_remove_speculative(include_speculative); + t = t->maybe_remove_speculative(include_speculative); + + const Type *mt = this_t->xmeet(t); if (isa_narrowoop() || t->isa_narrowoop()) return mt; if (isa_narrowklass() || t->isa_narrowklass()) return mt; #ifdef ASSERT - assert( mt == t->xmeet(this), "meet not commutative" ); + assert(mt == t->xmeet(this_t), "meet not commutative"); const Type* dual_join = mt->_dual; const Type *t2t = dual_join->xmeet(t->_dual); - const Type *t2this = dual_join->xmeet( _dual); + const Type *t2this = dual_join->xmeet(this_t->_dual); // Interface meet Oop is Not Symmetric: // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull - if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != _dual) ) { + if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this_t->_dual) ) { tty->print_cr("=== Meet Not Symmetric ==="); - tty->print("t = "); t->dump(); tty->cr(); - tty->print("this= "); dump(); tty->cr(); - tty->print("mt=(t meet this)= "); mt->dump(); tty->cr(); + tty->print("t = "); t->dump(); tty->cr(); + tty->print("this= "); this_t->dump(); tty->cr(); + tty->print("mt=(t meet this)= "); mt->dump(); tty->cr(); - tty->print("t_dual= "); t->_dual->dump(); tty->cr(); - tty->print("this_dual= "); _dual->dump(); tty->cr(); - tty->print("mt_dual= "); mt->_dual->dump(); tty->cr(); + tty->print("t_dual= "); t->_dual->dump(); tty->cr(); + tty->print("this_dual= "); this_t->_dual->dump(); tty->cr(); + tty->print("mt_dual= "); mt->_dual->dump(); tty->cr(); - tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr(); - tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr(); + tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr(); + tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr(); fatal("meet not symmetric" ); } @@ -754,8 +764,8 @@ const Type *Type::xmeet( const Type *t ) const { } //-----------------------------filter------------------------------------------ -const Type *Type::filter( const Type *kills ) const { - const Type* ft = join(kills); +const Type *Type::filter_helper(const Type *kills, bool include_speculative) const { + const Type* ft = join_helper(kills, include_speculative); if (ft->empty()) return Type::TOP; // Canonical empty value return ft; @@ -1309,8 +1319,8 @@ const Type *TypeInt::narrow( const Type *old ) const { } //-----------------------------filter------------------------------------------ -const Type *TypeInt::filter( const Type *kills ) const { - const TypeInt* ft = join(kills)->isa_int(); +const Type *TypeInt::filter_helper(const Type *kills, bool include_speculative) const { + const TypeInt* ft = join_helper(kills, include_speculative)->isa_int(); if (ft == NULL || ft->empty()) return Type::TOP; // Canonical empty value if (ft->_widen < this->_widen) { @@ -1570,8 +1580,8 @@ const Type *TypeLong::narrow( const Type *old ) const { } //-----------------------------filter------------------------------------------ -const Type *TypeLong::filter( const Type *kills ) const { - const TypeLong* ft = join(kills)->isa_long(); +const Type *TypeLong::filter_helper(const Type *kills, bool include_speculative) const { + const TypeLong* ft = join_helper(kills, include_speculative)->isa_long(); if (ft == NULL || ft->empty()) return Type::TOP; // Canonical empty value if (ft->_widen < this->_widen) { @@ -1726,7 +1736,7 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig) total_fields++; field_array = fields(total_fields); // Use get_const_type here because it respects UseUniqueSubclasses: - field_array[pos++] = get_const_type(recv)->join(TypePtr::NOTNULL); + field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL); } else { field_array = fields(total_fields); } @@ -1916,7 +1926,7 @@ const Type *TypeAry::xmeet( const Type *t ) const { case Array: { // Meeting 2 arrays? const TypeAry *a = t->is_ary(); - return TypeAry::make(_elem->meet(a->_elem), + return TypeAry::make(_elem->meet_speculative(a->_elem), _size->xmeet(a->_size)->is_int(), _stable & a->_stable); } @@ -1949,6 +1959,13 @@ int TypeAry::hash(void) const { return (intptr_t)_elem + (intptr_t)_size + (_stable ? 43 : 0); } +/** + * Return same type without a speculative part in the element + */ +const Type* TypeAry::remove_speculative() const { + return make(_elem->remove_speculative(), _size, _stable); +} + //----------------------interface_vs_oop--------------------------------------- #ifdef ASSERT bool TypeAry::interface_vs_oop(const Type *t) const { @@ -2560,14 +2577,14 @@ const Type *TypeOopPtr::xmeet(const Type *t) const { return res; } - if (res->isa_oopptr() != NULL) { + const TypeOopPtr* res_oopptr = res->is_oopptr(); + if (res_oopptr->speculative() != NULL) { // type->speculative() == NULL means that speculation is no better // than type, i.e. type->speculative() == type. So there are 2 // ways to represent the fact that we have no useful speculative // data and we should use a single one to be able to test for // equality between types. Check whether type->speculative() == // type and set speculative to NULL if it is the case. - const TypeOopPtr* res_oopptr = res->is_oopptr(); if (res_oopptr->remove_speculative() == res_oopptr->speculative()) { return res_oopptr->remove_speculative(); } @@ -2633,7 +2650,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { case OopPtr: { // Meeting to other OopPtrs const TypeOopPtr *tp = t->is_oopptr(); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative); } @@ -2787,9 +2804,9 @@ intptr_t TypeOopPtr::get_con() const { //-----------------------------filter------------------------------------------ // Do not allow interface-vs.-noninterface joins to collapse to top. -const Type *TypeOopPtr::filter(const Type *kills) const { +const Type *TypeOopPtr::filter_helper(const Type *kills, bool include_speculative) const { - const Type* ft = join(kills); + const Type* ft = join_helper(kills, include_speculative); const TypeInstPtr* ftip = ft->isa_instptr(); const TypeInstPtr* ktip = kills->isa_instptr(); @@ -2901,7 +2918,10 @@ const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { /** * Return same type without a speculative part */ -const TypeOopPtr* TypeOopPtr::remove_speculative() const { +const Type* TypeOopPtr::remove_speculative() const { + if (_speculative == NULL) { + return this; + } return make(_ptr, _offset, _instance_id, NULL); } @@ -2927,7 +2947,7 @@ int TypeOopPtr::dual_instance_id( ) const { * * @param other type to meet with */ -const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const { +const TypeOopPtr* TypeOopPtr::xmeet_speculative(const TypeOopPtr* other) const { bool this_has_spec = (_speculative != NULL); bool other_has_spec = (other->speculative() != NULL); @@ -2952,7 +2972,7 @@ const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const { other_spec = other; } - return this_spec->meet(other_spec)->is_oopptr(); + return this_spec->meet_speculative(other_spec)->is_oopptr(); } /** @@ -3111,7 +3131,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { int off = meet_offset(tinst->offset()); PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tinst); + const TypeOopPtr* speculative = xmeet_speculative(tinst); const TypeInstPtr *loaded = is_loaded() ? this : tinst; const TypeInstPtr *unloaded = is_loaded() ? tinst : this; @@ -3188,7 +3208,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3238,14 +3258,14 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); return make(ptr, klass(), klass_is_exact(), (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); } case NotNull: case BotPTR: { int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); return TypeOopPtr::make(ptr, offset, instance_id, speculative); } default: typerr(t); @@ -3297,7 +3317,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { int off = meet_offset( tinst->offset() ); PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tinst); + const TypeOopPtr* speculative = xmeet_speculative(tinst); // Check for easy case; klasses are equal (and perhaps not loaded!) // If we have constants, then we created oops so classes are loaded @@ -3546,7 +3566,10 @@ const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const { return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id, add_offset_speculative(offset)); } -const TypeOopPtr *TypeInstPtr::remove_speculative() const { +const Type *TypeInstPtr::remove_speculative() const { + if (_speculative == NULL) { + return this; + } return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL); } @@ -3748,14 +3771,14 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); return make(ptr, (ptr == Constant ? const_oop() : NULL), _ary, _klass, _klass_is_exact, offset, instance_id, speculative); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); return TypeOopPtr::make(ptr, offset, instance_id, speculative); } default: ShouldNotReachHere(); @@ -3793,10 +3816,10 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { case AryPtr: { // Meeting 2 references? const TypeAryPtr *tap = t->is_aryptr(); int off = meet_offset(tap->offset()); - const TypeAry *tary = _ary->meet(tap->_ary)->is_ary(); + const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary(); PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tap); + const TypeOopPtr* speculative = xmeet_speculative(tap); ciKlass* lazy_klass = NULL; if (tary->_elem->isa_int()) { // Integral array element types have irrelevant lattice relations. @@ -3876,7 +3899,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = meet_speculative(tp); + const TypeOopPtr* speculative = xmeet_speculative(tp); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3990,8 +4013,8 @@ const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); } -const TypeOopPtr *TypeAryPtr::remove_speculative() const { - return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, _offset, _instance_id, NULL); +const Type *TypeAryPtr::remove_speculative() const { + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL); } //============================================================================= @@ -4031,9 +4054,9 @@ const Type *TypeNarrowPtr::xdual() const { // Compute dual right now. } -const Type *TypeNarrowPtr::filter( const Type *kills ) const { +const Type *TypeNarrowPtr::filter_helper(const Type *kills, bool include_speculative) const { if (isa_same_narrowptr(kills)) { - const Type* ft =_ptrtype->filter(is_same_narrowptr(kills)->_ptrtype); + const Type* ft =_ptrtype->filter_helper(is_same_narrowptr(kills)->_ptrtype, include_speculative); if (ft->empty()) return Type::TOP; // Canonical empty value if (ft->isa_ptr()) { @@ -4041,7 +4064,7 @@ const Type *TypeNarrowPtr::filter( const Type *kills ) const { } return ft; } else if (kills->isa_ptr()) { - const Type* ft = _ptrtype->join(kills); + const Type* ft = _ptrtype->join_helper(kills, include_speculative); if (ft->empty()) return Type::TOP; // Canonical empty value return ft; @@ -4171,8 +4194,8 @@ const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const { //-----------------------------filter------------------------------------------ // Do not allow interface-vs.-noninterface joins to collapse to top. -const Type *TypeMetadataPtr::filter( const Type *kills ) const { - const TypeMetadataPtr* ft = join(kills)->isa_metadataptr(); +const Type *TypeMetadataPtr::filter_helper(const Type *kills, bool include_speculative) const { + const TypeMetadataPtr* ft = join_helper(kills, include_speculative)->isa_metadataptr(); if (ft == NULL || ft->empty()) return Type::TOP; // Canonical empty value return ft; @@ -4374,10 +4397,10 @@ bool TypeKlassPtr::singleton(void) const { } // Do not allow interface-vs.-noninterface joins to collapse to top. -const Type *TypeKlassPtr::filter(const Type *kills) const { +const Type *TypeKlassPtr::filter_helper(const Type *kills, bool include_speculative) const { // logic here mirrors the one from TypeOopPtr::filter. See comments // there. - const Type* ft = join(kills); + const Type* ft = join_helper(kills, include_speculative); const TypeKlassPtr* ftkp = ft->isa_klassptr(); const TypeKlassPtr* ktkp = kills->isa_klassptr(); diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 9810edfe724..747c29c5d0f 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -164,6 +164,8 @@ private: virtual bool interface_vs_oop_helper(const Type *t) const; #endif + const Type *meet_helper(const Type *t, bool include_speculative) const; + protected: // Each class of type is also identified by its base. const TYPES _base; // Enum of Types type @@ -171,6 +173,10 @@ protected: Type( TYPES t ) : _dual(NULL), _base(t) {} // Simple types // ~Type(); // Use fast deallocation const Type *hashcons(); // Hash-cons the type + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; + const Type *join_helper(const Type *t, bool include_speculative) const { + return dual()->meet_helper(t->dual(), include_speculative)->dual(); + } public: @@ -202,10 +208,24 @@ public: // Test for equivalence of types static int cmp( const Type *const t1, const Type *const t2 ); // Test for higher or equal in lattice - int higher_equal( const Type *t ) const { return !cmp(meet(t),t); } + // Variant that drops the speculative part of the types + int higher_equal(const Type *t) const { + return !cmp(meet(t),t->remove_speculative()); + } + // Variant that keeps the speculative part of the types + int higher_equal_speculative(const Type *t) const { + return !cmp(meet_speculative(t),t); + } // MEET operation; lower in lattice. - const Type *meet( const Type *t ) const; + // Variant that drops the speculative part of the types + const Type *meet(const Type *t) const { + return meet_helper(t, false); + } + // Variant that keeps the speculative part of the types + const Type *meet_speculative(const Type *t) const { + return meet_helper(t, true); + } // WIDEN: 'widens' for Ints and other range types virtual const Type *widen( const Type *old, const Type* limit ) const { return this; } // NARROW: complement for widen, used by pessimistic phases @@ -221,13 +241,26 @@ public: // JOIN operation; higher in lattice. Done by finding the dual of the // meet of the dual of the 2 inputs. - const Type *join( const Type *t ) const { - return dual()->meet(t->dual())->dual(); } + // Variant that drops the speculative part of the types + const Type *join(const Type *t) const { + return join_helper(t, false); + } + // Variant that keeps the speculative part of the types + const Type *join_speculative(const Type *t) const { + return join_helper(t, true); + } // Modified version of JOIN adapted to the needs Node::Value. // Normalizes all empty values to TOP. Does not kill _widen bits. // Currently, it also works around limitations involving interface types. - virtual const Type *filter( const Type *kills ) const; + // Variant that drops the speculative part of the types + const Type *filter(const Type *kills) const { + return filter_helper(kills, false); + } + // Variant that keeps the speculative part of the types + const Type *filter_speculative(const Type *kills) const { + return filter_helper(kills, true); + } #ifdef ASSERT // One type is interface, the other is oop @@ -383,6 +416,8 @@ public: // Speculative type. See TypeInstPtr virtual ciKlass* speculative_type() const { return NULL; } + const Type* maybe_remove_speculative(bool include_speculative) const; + virtual const Type* remove_speculative() const { return this; } private: // support arrays @@ -450,12 +485,14 @@ public: // upper bound, inclusive. class TypeInt : public Type { TypeInt( jint lo, jint hi, int w ); +protected: + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; + public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous -public: const jint _lo, _hi; // Lower bound, upper bound const short _widen; // Limit on times we widen this sucker @@ -475,7 +512,6 @@ public: virtual const Type *widen( const Type *t, const Type* limit_type ) const; virtual const Type *narrow( const Type *t ) const; // Do not kill _widen bits. - virtual const Type *filter( const Type *kills ) const; // Convenience common pre-built types. static const TypeInt *MINUS_1; static const TypeInt *ZERO; @@ -506,6 +542,9 @@ public: // an upper bound, inclusive. class TypeLong : public Type { TypeLong( jlong lo, jlong hi, int w ); +protected: + // Do not kill _widen bits. + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -530,8 +569,6 @@ public: virtual const Type *xdual() const; // Compute dual right now. virtual const Type *widen( const Type *t, const Type* limit_type ) const; virtual const Type *narrow( const Type *t ) const; - // Do not kill _widen bits. - virtual const Type *filter( const Type *kills ) const; // Convenience common pre-built types. static const TypeLong *MINUS_1; static const TypeLong *ZERO; @@ -622,6 +659,7 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. bool ary_must_be_exact() const; // true if arrays of such are never generic + virtual const Type* remove_speculative() const; #ifdef ASSERT // One type is interface, the other is oop virtual bool interface_vs_oop(const Type *t) const; @@ -832,7 +870,7 @@ protected: // utility methods to work on the speculative part of the type const TypeOopPtr* dual_speculative() const; - const TypeOopPtr* meet_speculative(const TypeOopPtr* other) const; + const TypeOopPtr* xmeet_speculative(const TypeOopPtr* other) const; bool eq_speculative(const TypeOopPtr* other) const; int hash_speculative() const; const TypeOopPtr* add_offset_speculative(intptr_t offset) const; @@ -840,6 +878,9 @@ protected: void dump_speculative(outputStream *st) const; #endif + // Do not allow interface-vs.-noninterface joins to collapse to top. + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; + public: // Creates a type given a klass. Correctly handles multi-dimensional arrays // Respects UseUniqueSubclasses. @@ -895,16 +936,13 @@ public: virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part - virtual const TypeOopPtr* remove_speculative() const; + virtual const Type* remove_speculative() const; virtual const Type *xmeet(const Type *t) const; virtual const Type *xdual() const; // Compute dual right now. // the core of the computation of the meet for TypeOopPtr and for its subclasses virtual const Type *xmeet_helper(const Type *t) const; - // Do not allow interface-vs.-noninterface joins to collapse to top. - virtual const Type *filter( const Type *kills ) const; - // Convenience common pre-built type. static const TypeOopPtr *BOTTOM; #ifndef PRODUCT @@ -981,7 +1019,7 @@ class TypeInstPtr : public TypeOopPtr { virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part - virtual const TypeOopPtr* remove_speculative() const; + virtual const Type* remove_speculative() const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1059,7 +1097,7 @@ public: virtual bool empty(void) const; // TRUE if type is vacuous virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part - virtual const TypeOopPtr* remove_speculative() const; + virtual const Type* remove_speculative() const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1100,6 +1138,8 @@ public: class TypeMetadataPtr : public TypePtr { protected: TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset); + // Do not allow interface-vs.-noninterface joins to collapse to top. + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1125,9 +1165,6 @@ public: virtual intptr_t get_con() const; - // Do not allow interface-vs.-noninterface joins to collapse to top. - virtual const Type *filter( const Type *kills ) const; - // Convenience common pre-built types. static const TypeMetadataPtr *BOTTOM; @@ -1141,6 +1178,8 @@ public: class TypeKlassPtr : public TypePtr { TypeKlassPtr( PTR ptr, ciKlass* klass, int offset ); +protected: + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1202,9 +1241,6 @@ public: virtual intptr_t get_con() const; - // Do not allow interface-vs.-noninterface joins to collapse to top. - virtual const Type *filter( const Type *kills ) const; - // Convenience common pre-built types. static const TypeKlassPtr* OBJECT; // Not-null object klass or below static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same @@ -1228,6 +1264,8 @@ protected: virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const = 0; virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const = 0; virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const = 0; + // Do not allow interface-vs.-noninterface joins to collapse to top. + virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1238,9 +1276,6 @@ public: virtual intptr_t get_con() const; - // Do not allow interface-vs.-noninterface joins to collapse to top. - virtual const Type *filter( const Type *kills ) const; - virtual bool empty(void) const; // TRUE if type is vacuous // returns the equivalent ptr type for this compressed pointer @@ -1291,6 +1326,10 @@ public: static const TypeNarrowOop *BOTTOM; static const TypeNarrowOop *NULL_PTR; + virtual const Type* remove_speculative() const { + return make(_ptrtype->remove_speculative()->is_ptr()); + } + #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const; #endif diff --git a/hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java b/hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java new file mode 100644 index 00000000000..9579dce6e40 --- /dev/null +++ b/hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8027422 + * @summary type methods shouldn't always operate on speculative part + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TypeProfileLevel=222 -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestSpeculationFailedHigherEqual + * + */ + +public class TestSpeculationFailedHigherEqual { + + static class A { + void m() {} + int i; + } + + static class C extends A { + } + + static C c; + + static A m1(A a, boolean cond) { + // speculative type for a is C not null + if (cond ) { + a = c; + } + // speculative type for a is C (may be null) + int i = a.i; + return a; + } + + static public void main(String[] args) { + C c = new C(); + TestSpeculationFailedHigherEqual.c = c; + for (int i = 0; i < 20000; i++) { + m1(c, i%2 == 0); + } + + System.out.println("TEST PASSED"); + } +} From 6eddc19daf1299b44dccd92d1b009690aa4bae02 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 24 Jan 2014 10:23:34 +0100 Subject: [PATCH 104/265] 8032634: Add #ifdef PPC64 around OrderAccess operations on _thread_state Reviewed-by: dholmes, kvn --- hotspot/src/share/vm/runtime/thread.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 94cca352c26..2cc5c7eeb55 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1033,17 +1033,21 @@ class JavaThread: public Thread { // Last frame anchor routines - JavaFrameAnchor* frame_anchor(void) { return &_anchor; } + JavaFrameAnchor* frame_anchor(void) { return &_anchor; } // last_Java_sp - bool has_last_Java_frame() const { return _anchor.has_last_Java_frame(); } - intptr_t* last_Java_sp() const { return _anchor.last_Java_sp(); } + bool has_last_Java_frame() const { return _anchor.has_last_Java_frame(); } + intptr_t* last_Java_sp() const { return _anchor.last_Java_sp(); } // last_Java_pc - address last_Java_pc(void) { return _anchor.last_Java_pc(); } + address last_Java_pc(void) { return _anchor.last_Java_pc(); } // Safepoint support +#ifndef PPC64 + JavaThreadState thread_state() const { return _thread_state; } + void set_thread_state(JavaThreadState s) { _thread_state = s; } +#else // Use membars when accessing volatile _thread_state. See // Threads::create_vm() for size checks. JavaThreadState thread_state() const { @@ -1052,7 +1056,8 @@ class JavaThread: public Thread { void set_thread_state(JavaThreadState s) { OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s); } - ThreadSafepointState *safepoint_state() const { return _safepoint_state; } +#endif + ThreadSafepointState *safepoint_state() const { return _safepoint_state; } void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; } bool is_at_poll_safepoint() { return _safepoint_state->is_at_poll_safepoint(); } From fbff3b73a4f436e345f68deaf58786f83152acae Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 24 Jan 2014 15:26:56 +0400 Subject: [PATCH 105/265] 8032490: Remove -XX:+-UseOldInlining Move the option to obsolete options list, purge the redundant compiler code. Reviewed-by: kvn, jrose --- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 88 ++++------------------ hotspot/src/share/vm/opto/c2_globals.hpp | 3 - hotspot/src/share/vm/opto/compile.cpp | 5 +- hotspot/src/share/vm/opto/doCall.cpp | 13 +--- hotspot/src/share/vm/runtime/arguments.cpp | 1 + 5 files changed, 17 insertions(+), 93 deletions(-) diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 4b3f39f0893..101d5f73325 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -63,34 +63,14 @@ InlineTree::InlineTree(Compile* c, assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); assert((caller_tree == NULL ? 0 : caller_tree->stack_depth() + 1) == stack_depth(), "correct (redundant) depth parameter"); assert(caller_bci == this->caller_bci(), "correct (redundant) bci parameter"); - if (UseOldInlining) { - // Update hierarchical counts, count_inline_bcs() and count_inlines() - InlineTree *caller = (InlineTree *)caller_tree; - for( ; caller != NULL; caller = ((InlineTree *)(caller->caller_tree())) ) { - caller->_count_inline_bcs += count_inline_bcs(); - NOT_PRODUCT(caller->_count_inlines++;) - } + // Update hierarchical counts, count_inline_bcs() and count_inlines() + InlineTree *caller = (InlineTree *)caller_tree; + for( ; caller != NULL; caller = ((InlineTree *)(caller->caller_tree())) ) { + caller->_count_inline_bcs += count_inline_bcs(); + NOT_PRODUCT(caller->_count_inlines++;) } } -InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, - float site_invoke_ratio, int max_inline_level) : - C(c), - _caller_jvms(caller_jvms), - _caller_tree(NULL), - _method(callee_method), - _site_invoke_ratio(site_invoke_ratio), - _max_inline_level(max_inline_level), - _count_inline_bcs(method()->code_size()), - _msg(NULL) -{ -#ifndef PRODUCT - _count_inlines = 0; - _forced_inline = false; -#endif - assert(!UseOldInlining, "do not use for old stuff"); -} - /** * Return true when EA is ON and a java constructor is called or * a super constructor is called from an inlined java constructor. @@ -161,11 +141,6 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, return true; } - if (!UseOldInlining) { - set_msg("!UseOldInlining"); - return true; // size and frequency are represented in a new way - } - int default_max_inline_size = C->max_inline_size(); int inline_small_code_size = InlineSmallCode / 4; int max_inline_size = default_max_inline_size; @@ -229,35 +204,6 @@ bool InlineTree::should_not_inline(ciMethod *callee_method, fail_msg = "don't inline by annotation"; } - if (!UseOldInlining) { - if (fail_msg != NULL) { - *wci_result = *(WarmCallInfo::always_cold()); - set_msg(fail_msg); - return true; - } - - if (callee_method->has_unloaded_classes_in_signature()) { - wci_result->set_profit(wci_result->profit() * 0.1); - } - - // don't inline exception code unless the top method belongs to an - // exception class - if (callee_method->holder()->is_subclass_of(C->env()->Throwable_klass())) { - ciMethod* top_method = jvms->caller() != NULL ? jvms->caller()->of_depth(1)->method() : method(); - if (!top_method->holder()->is_subclass_of(C->env()->Throwable_klass())) { - wci_result->set_profit(wci_result->profit() * 0.1); - } - } - - if (callee_method->has_compiled_code() && - callee_method->instructions_size() > InlineSmallCode) { - wci_result->set_profit(wci_result->profit() * 0.1); - // %%% adjust wci_result->size()? - } - - return false; - } - // one more inlining restriction if (fail_msg == NULL && callee_method->has_unloaded_classes_in_signature()) { fail_msg = "unloaded signature classes"; @@ -360,9 +306,7 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) { - // Old algorithm had funny accumulating BC-size counters - if (UseOldInlining && ClipInlining - && (int)count_inline_bcs() >= DesiredMethodLimit) { + if (ClipInlining && (int)count_inline_bcs() >= DesiredMethodLimit) { if (!callee_method->force_inline() || !IncrementalInline) { set_msg("size > DesiredMethodLimit"); return false; @@ -465,8 +409,7 @@ bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int size = callee_method->code_size_for_inlining(); - if (UseOldInlining && ClipInlining - && (int)count_inline_bcs() + size >= DesiredMethodLimit) { + if (ClipInlining && (int)count_inline_bcs() + size >= DesiredMethodLimit) { if (!callee_method->force_inline() || !IncrementalInline) { set_msg("size > DesiredMethodLimit"); return false; @@ -584,8 +527,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, jvms, profile, &wci, should_delay); #ifndef PRODUCT - if (UseOldInlining && InlineWarmCalls - && (PrintOpto || C->print_inlining())) { + if (InlineWarmCalls && (PrintOpto || C->print_inlining())) { bool cold = wci.is_cold(); bool hot = !cold && wci.is_hot(); bool old_cold = !success; @@ -599,13 +541,12 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } } #endif - if (UseOldInlining) { - if (success) { - wci = *(WarmCallInfo::always_hot()); - } else { - wci = *(WarmCallInfo::always_cold()); - } + if (success) { + wci = *(WarmCallInfo::always_hot()); + } else { + wci = *(WarmCallInfo::always_cold()); } + if (!InlineWarmCalls) { if (!wci.is_cold() && !wci.is_hot()) { // Do not inline the warm calls. @@ -619,8 +560,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, set_msg("inline (hot)"); } print_inlining(callee_method, caller_bci, true /* success */); - if (UseOldInlining) - build_inline_tree_for_callee(callee_method, jvms, caller_bci); + build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) return new (C) WarmCallInfo(wci); // copy to heap return WarmCallInfo::always_hot(); diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 207daabc7b3..e478d99ab03 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -350,9 +350,6 @@ "File to dump ideal graph to. If set overrides the " \ "use of the network") \ \ - product(bool, UseOldInlining, true, \ - "Enable the 1.3 inlining strategy") \ - \ product(bool, UseBimorphicInlining, true, \ "Profiling based inlining for two receivers") \ \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 80acf7f317c..10b62f33621 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -701,10 +701,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr print_compile_messages(); - if (UseOldInlining || PrintCompilation NOT_PRODUCT( || PrintOpto) ) - _ilt = InlineTree::build_inline_tree_root(); - else - _ilt = NULL; + _ilt = InlineTree::build_inline_tree_root(); // Even if NO memory addresses are used, MergeMem nodes must have at least 1 slice assert(num_alias_types() >= AliasIdxRaw, ""); diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 223f7da3655..e888b550f66 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -161,19 +161,8 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool // Try inlining a bytecoded method: if (!call_does_dispatch) { - InlineTree* ilt; - if (UseOldInlining) { - ilt = InlineTree::find_subtree_from_root(this->ilt(), jvms->caller(), jvms->method()); - } else { - // Make a disembodied, stateless ILT. - // TO DO: When UseOldInlining is removed, copy the ILT code elsewhere. - float site_invoke_ratio = prof_factor; - // Note: ilt is for the root of this parse, not the present call site. - ilt = new InlineTree(this, jvms->method(), jvms->caller(), site_invoke_ratio, MaxInlineLevel); - } + InlineTree* ilt = InlineTree::find_subtree_from_root(this->ilt(), jvms->caller(), jvms->method()); WarmCallInfo scratch_ci; - if (!UseOldInlining) - scratch_ci.init(jvms, callee, profile, prof_factor); bool should_delay = false; WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci, should_delay); assert(ci != &scratch_ci, "do not let this pointer escape"); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 2769eece609..302e6775822 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -290,6 +290,7 @@ static ObsoleteFlag obsolete_jvm_flags[] = { { "UsePermISM", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseMPSS", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseStringCache", JDK_Version::jdk(8), JDK_Version::jdk(9) }, + { "UseOldInlining", JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef PRODUCT { "DesiredMethodLimit", JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, From 62f89da6655a31208db2a9c2593292644cf83d91 Mon Sep 17 00:00:00 2001 From: Albert Noll Date: Mon, 27 Jan 2014 07:54:25 +0100 Subject: [PATCH 106/265] 8009738: compiler/6826736/Test.java times out on big machines Added -Xmx256m -XX:ParallelGCThreads=4 to the test @run command. Verified that 256m is enough to trigger old 6826736 bug. Reviewed-by: kvn --- hotspot/test/compiler/6826736/Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/test/compiler/6826736/Test.java b/hotspot/test/compiler/6826736/Test.java index 63299ddc4af..e1e1e8d2341 100644 --- a/hotspot/test/compiler/6826736/Test.java +++ b/hotspot/test/compiler/6826736/Test.java @@ -27,7 +27,7 @@ * @bug 6826736 * @summary CMS: core dump with -XX:+UseCompressedOops * - * @run main/othervm/timeout=600 -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:CompileThreshold=100 -XX:CompileOnly=Test.test -XX:-BlockLayoutRotateLoops -XX:LoopUnrollLimit=0 Test + * @run main/othervm/timeout=600 -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:CompileThreshold=100 -XX:CompileOnly=Test.test -XX:-BlockLayoutRotateLoops -XX:LoopUnrollLimit=0 -Xmx256m -XX:ParallelGCThreads=4 Test */ public class Test { From 970a35292b77cf9d73c03944d60780a6a7466a49 Mon Sep 17 00:00:00 2001 From: Niclas Adlertz Date: Fri, 24 Jan 2014 13:06:52 +0100 Subject: [PATCH 107/265] 8031498: Cleanup and re-factorize PhaseChaitin::build_ifg_physical Created sub-functions, added data structures, improved naming and removed unnecessary code Reviewed-by: kvn, roland, rbackman --- hotspot/src/share/vm/opto/chaitin.hpp | 81 ++- hotspot/src/share/vm/opto/ifg.cpp | 776 ++++++++++++++------------ 2 files changed, 487 insertions(+), 370 deletions(-) diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index b188cc9bbf8..fb114bbd930 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -98,6 +98,12 @@ public: } // Compute the degree between 2 live ranges int compute_degree( LRG &l ) const; + bool mask_is_nonempty_and_up() const { + return mask().is_UP() && mask_size(); + } + bool is_float_or_vector() const { + return _is_float || _is_vector; + } private: RegMask _mask; // Allowed registers for this LRG @@ -129,6 +135,7 @@ public: void SUBTRACT( const RegMask &rm ) { _mask.SUBTRACT(rm); debug_only(_msize_valid=0;)} void Clear() { _mask.Clear() ; debug_only(_msize_valid=1); _mask_size = 0; } void Set_All() { _mask.Set_All(); debug_only(_msize_valid=1); _mask_size = RegMask::CHUNK_SIZE; } + void Insert( OptoReg::Name reg ) { _mask.Insert(reg); debug_only(_msize_valid=0;) } void Remove( OptoReg::Name reg ) { _mask.Remove(reg); debug_only(_msize_valid=0;) } void clear_to_pairs() { _mask.clear_to_pairs(); debug_only(_msize_valid=0;) } @@ -483,15 +490,75 @@ private: // Same as _ifg->add_vector(reg,live) EXCEPT use the RegMask // information to trim the set of interferences. Return the // count of edges added. - void interfere_with_live( uint reg, IndexSet *live ); + void interfere_with_live(uint lid, IndexSet* liveout); +#ifdef ASSERT // Count register pressure for asserts - uint count_int_pressure( IndexSet *liveout ); - uint count_float_pressure( IndexSet *liveout ); + uint count_int_pressure(IndexSet* liveout); + uint count_float_pressure(IndexSet* liveout); +#endif // Build the interference graph using virtual registers only. // Used for aggressive coalescing. void build_ifg_virtual( ); + class Pressure { + public: + // keeps track of the register pressure at the current + // instruction (used when stepping backwards in the block) + uint _current_pressure; + + // keeps track of the instruction index of the first low to high register pressure + // transition (starting from the top) in the block + // if high_pressure_index == 0 then the whole block is high pressure + // if high_pressure_index = b.end_idx() + 1 then the whole block is low pressure + uint _high_pressure_index; + + // stores the highest pressure we find + uint _final_pressure; + + // number of live ranges that constitute high register pressure + const uint _high_pressure_limit; + + // lower the register pressure and look for a low to high pressure + // transition + void lower(LRG& lrg, uint& location) { + _current_pressure -= lrg.reg_pressure(); + if (_current_pressure == _high_pressure_limit) { + _high_pressure_index = location; + if (_current_pressure > _final_pressure) { + _final_pressure = _current_pressure + 1; + } + } + } + + // raise the pressure and store the pressure if it's the biggest + // pressure so far + void raise(LRG &lrg) { + _current_pressure += lrg.reg_pressure(); + if (_current_pressure > _final_pressure) { + _final_pressure = _current_pressure; + } + } + + Pressure(uint high_pressure_index, uint high_pressure_limit) + : _current_pressure(0) + , _high_pressure_index(high_pressure_index) + , _high_pressure_limit(high_pressure_limit) + , _final_pressure(0) {} + }; + + void lower_pressure(Block* b, uint location, LRG& lrg, IndexSet* liveout, Pressure& int_pressure, Pressure& float_pressure); + void raise_pressure(Block* b, LRG& lrg, Pressure& int_pressure, Pressure& float_pressure); + void check_for_high_pressure_transition_at_fatproj(uint& block_reg_pressure, uint location, LRG& lrg, Pressure& pressure, const int op_regtype); + void add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, double cost, Pressure& int_pressure, Pressure& float_pressure); + void compute_initial_block_pressure(Block* b, IndexSet* liveout, Pressure& int_pressure, Pressure& float_pressure, double cost); + bool remove_node_if_not_used(Block* b, uint location, Node* n, uint lid, IndexSet* liveout); + void assign_high_score_to_immediate_copies(Block* b, Node* n, LRG& lrg, uint next_inst, uint last_inst); + void remove_interference_from_copy(Block* b, uint location, uint lid_copy, IndexSet* liveout, double cost, Pressure& int_pressure, Pressure& float_pressure); + void remove_bound_register_from_interfering_live_ranges(LRG& lrg, IndexSet* liveout, uint& must_spill); + void check_for_high_pressure_block(Pressure& pressure); + void adjust_high_pressure_index(Block* b, uint& hrp_index, Pressure& pressure); + // Build the interference graph using physical registers when available. // That is, if 2 live ranges are simultaneously alive but in their // acceptable register sets do not overlap, then they do not interfere. @@ -554,7 +621,7 @@ private: // Replace the old node with the current live version of that value // and yank the old value if it's dead. int replace_and_yank_if_dead( Node *old, OptoReg::Name nreg, - Block *current_block, Node_List& value, Node_List& regnd ) { + Block *current_block, Node_List& value, Node_List& regnd ) { Node* v = regnd[nreg]; assert(v->outcnt() != 0, "no dead values"); old->replace_by(v); @@ -565,7 +632,7 @@ private: return yank_if_dead_recurse(old, old, current_block, value, regnd); } int yank_if_dead_recurse(Node *old, Node *orig_old, Block *current_block, - Node_List *value, Node_List *regnd); + Node_List *value, Node_List *regnd); int yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ); int elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs ); int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd ); @@ -573,8 +640,8 @@ private: // If nreg already contains the same constant as val then eliminate it bool eliminate_copy_of_constant(Node* val, Node* n, - Block *current_block, Node_List& value, Node_List ®nd, - OptoReg::Name nreg, OptoReg::Name nreg2); + Block *current_block, Node_List& value, Node_List ®nd, + OptoReg::Name nreg, OptoReg::Name nreg2); // Extend the node to LRG mapping void add_reference( const Node *node, const Node *old_node); diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 52a6cecce90..24aab15143f 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -281,20 +281,23 @@ void PhaseIFG::verify( const PhaseChaitin *pc ) const { } #endif -// Interfere this register with everything currently live. Use the RegMasks -// to trim the set of possible interferences. Return a count of register-only -// interferences as an estimate of register pressure. -void PhaseChaitin::interfere_with_live( uint r, IndexSet *liveout ) { - uint retval = 0; - // Interfere with everything live. - const RegMask &rm = lrgs(r).mask(); - // Check for interference by checking overlap of regmasks. - // Only interfere if acceptable register masks overlap. +/* + * Interfere this register with everything currently live. + * Check for interference by checking overlap of regmasks. + * Only interfere if acceptable register masks overlap. + */ +void PhaseChaitin::interfere_with_live(uint lid, IndexSet* liveout) { + LRG& lrg = lrgs(lid); + const RegMask& rm = lrg.mask(); IndexSetIterator elements(liveout); - uint l; - while( (l = elements.next()) != 0 ) - if( rm.overlap( lrgs(l).mask() ) ) - _ifg->add_edge( r, l ); + uint interfering_lid = elements.next(); + while (interfering_lid != 0) { + LRG& interfering_lrg = lrgs(interfering_lid); + if (rm.overlap(interfering_lrg.mask())) { + _ifg->add_edge(lid, interfering_lid); + } + interfering_lid = elements.next(); + } } // Actually build the interference graph. Uses virtual registers only, no @@ -333,7 +336,7 @@ void PhaseChaitin::build_ifg_virtual( ) { // Copies do not define a new value and so do not interfere. // Remove the copies source from the liveout set before interfering. uint idx = n->is_Copy(); - if (idx) { + if (idx != 0) { liveout->remove(_lrg_map.live_range_id(n->in(idx))); } @@ -389,418 +392,465 @@ void PhaseChaitin::build_ifg_virtual( ) { } // End of forall blocks } -uint PhaseChaitin::count_int_pressure( IndexSet *liveout ) { +#ifdef ASSERT +uint PhaseChaitin::count_int_pressure(IndexSet* liveout) { IndexSetIterator elements(liveout); - uint lidx; + uint lidx = elements.next(); uint cnt = 0; - while ((lidx = elements.next()) != 0) { - if( lrgs(lidx).mask().is_UP() && - lrgs(lidx).mask_size() && - !lrgs(lidx)._is_float && - !lrgs(lidx)._is_vector && - lrgs(lidx).mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) - cnt += lrgs(lidx).reg_pressure(); + while (lidx != 0) { + LRG& lrg = lrgs(lidx); + if (lrg.mask_is_nonempty_and_up() && + !lrg.is_float_or_vector() && + lrg.mask().overlap(*Matcher::idealreg2regmask[Op_RegI])) { + cnt += lrg.reg_pressure(); + } + lidx = elements.next(); } return cnt; } -uint PhaseChaitin::count_float_pressure( IndexSet *liveout ) { +uint PhaseChaitin::count_float_pressure(IndexSet* liveout) { IndexSetIterator elements(liveout); - uint lidx; + uint lidx = elements.next(); uint cnt = 0; - while ((lidx = elements.next()) != 0) { - if( lrgs(lidx).mask().is_UP() && - lrgs(lidx).mask_size() && - (lrgs(lidx)._is_float || lrgs(lidx)._is_vector)) - cnt += lrgs(lidx).reg_pressure(); + while (lidx != 0) { + LRG& lrg = lrgs(lidx); + if (lrg.mask_is_nonempty_and_up() && lrg.is_float_or_vector()) { + cnt += lrg.reg_pressure(); + } + lidx = elements.next(); } return cnt; } +#endif -// Adjust register pressure down by 1. Capture last hi-to-low transition, -static void lower_pressure( LRG *lrg, uint where, Block *b, uint *pressure, uint *hrp_index ) { - if (lrg->mask().is_UP() && lrg->mask_size()) { - if (lrg->_is_float || lrg->_is_vector) { - pressure[1] -= lrg->reg_pressure(); - if( pressure[1] == (uint)FLOATPRESSURE ) { - hrp_index[1] = where; - if( pressure[1] > b->_freg_pressure ) - b->_freg_pressure = pressure[1]+1; +/* + * Adjust register pressure down by 1. Capture last hi-to-low transition, + */ +void PhaseChaitin::lower_pressure(Block* b, uint location, LRG& lrg, IndexSet* liveout, Pressure& int_pressure, Pressure& float_pressure) { + if (lrg.mask_is_nonempty_and_up()) { + if (lrg.is_float_or_vector()) { + float_pressure.lower(lrg, location); + } else { + // Do not count the SP and flag registers + const RegMask& r = lrg.mask(); + if (r.overlap(*Matcher::idealreg2regmask[Op_RegI])) { + int_pressure.lower(lrg, location); } - } else if( lrg->mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) { - pressure[0] -= lrg->reg_pressure(); - if( pressure[0] == (uint)INTPRESSURE ) { - hrp_index[0] = where; - if( pressure[0] > b->_reg_pressure ) - b->_reg_pressure = pressure[0]+1; + } + } + assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); +} + +/* Go to the first non-phi index in a block */ +static uint first_nonphi_index(Block* b) { + uint i; + uint end_idx = b->end_idx(); + for (i = 1; i < end_idx; i++) { + Node* n = b->get_node(i); + if (!n->is_Phi()) { + break; + } + } + return i; +} + +/* + * Spills could be inserted before a CreateEx node which should be the first + * instruction in a block after Phi nodes. If so, move the CreateEx node up. + */ +static void move_exception_node_up(Block* b, uint first_inst, uint last_inst) { + for (uint i = first_inst; i < last_inst; i++) { + Node* ex = b->get_node(i); + if (ex->is_SpillCopy()) { + continue; + } + + if (i > first_inst && + ex->is_Mach() && ex->as_Mach()->ideal_Opcode() == Op_CreateEx) { + b->remove_node(i); + b->insert_node(ex, first_inst); + } + // Stop once a CreateEx or any other node is found + break; + } +} + +/* + * When new live ranges are live, we raise the register pressure + */ +void PhaseChaitin::raise_pressure(Block* b, LRG& lrg, Pressure& int_pressure, Pressure& float_pressure) { + if (lrg.mask_is_nonempty_and_up()) { + if (lrg.is_float_or_vector()) { + float_pressure.raise(lrg); + } else { + // Do not count the SP and flag registers + const RegMask& rm = lrg.mask(); + if (rm.overlap(*Matcher::idealreg2regmask[Op_RegI])) { + int_pressure.raise(lrg); } } } } -// Build the interference graph using physical registers when available. -// That is, if 2 live ranges are simultaneously alive but in their acceptable -// register sets do not overlap, then they do not interfere. + +/* + * Computes the initial register pressure of a block, looking at all live + * ranges in the liveout. The register pressure is computed for both float + * and int/pointer registers. + * Live ranges in the liveout are presumed live for the whole block. + * We add the cost for the whole block to the area of the live ranges initially. + * If a live range gets killed in the block, we'll subtract the unused part of + * the block from the area. + */ +void PhaseChaitin::compute_initial_block_pressure(Block* b, IndexSet* liveout, Pressure& int_pressure, Pressure& float_pressure, double cost) { + IndexSetIterator elements(liveout); + uint lid = elements.next(); + while (lid != 0) { + LRG& lrg = lrgs(lid); + lrg._area += cost; + raise_pressure(b, lrg, int_pressure, float_pressure); + lid = elements.next(); + } + assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); +} + +/* + * Remove dead node if it's not used. + * We only remove projection nodes if the node "defining" the projection is + * dead, for example on x86, if we have a dead Add node we remove its + * RFLAGS node. + */ +bool PhaseChaitin::remove_node_if_not_used(Block* b, uint location, Node* n, uint lid, IndexSet* liveout) { + Node* def = n->in(0); + if (!n->is_Proj() || + (_lrg_map.live_range_id(def) && !liveout->member(_lrg_map.live_range_id(def)))) { + b->remove_node(location); + LRG& lrg = lrgs(lid); + if (lrg._def == n) { + lrg._def = 0; + } + n->disconnect_inputs(NULL, C); + _cfg.unmap_node_from_block(n); + n->replace_by(C->top()); + return true; + } + return false; +} + +/* + * When encountering a fat projection, we might go from a low to high to low + * (since the fat proj only lives at this instruction) going backwards in the + * block. If we find a low to high transition, we record it. + */ +void PhaseChaitin::check_for_high_pressure_transition_at_fatproj(uint& block_reg_pressure, uint location, LRG& lrg, Pressure& pressure, const int op_regtype) { + RegMask mask_tmp = lrg.mask(); + mask_tmp.AND(*Matcher::idealreg2regmask[op_regtype]); + // this pressure is only valid at this instruction, i.e. we don't need to lower + // the register pressure since the fat proj was never live before (going backwards) + uint new_pressure = pressure._current_pressure + mask_tmp.Size(); + if (new_pressure > pressure._final_pressure) { + pressure._final_pressure = new_pressure; + } + // if we were at a low pressure and now at the fat proj is at high pressure, record the fat proj location + // as coming from a low to high (to low again) + if (pressure._current_pressure <= pressure._high_pressure_limit && new_pressure > pressure._high_pressure_limit) { + pressure._high_pressure_index = location; + } +} + +/* + * Insure high score for immediate-use spill copies so they get a color. + * All single-use MachSpillCopy(s) that immediately precede their + * use must color early. If a longer live range steals their + * color, the spill copy will split and may push another spill copy + * further away resulting in an infinite spill-split-retry cycle. + * Assigning a zero area results in a high score() and a good + * location in the simplify list. + */ +void PhaseChaitin::assign_high_score_to_immediate_copies(Block* b, Node* n, LRG& lrg, uint next_inst, uint last_inst) { + if (n->is_SpillCopy() && + lrg.is_singledef() && // A multi defined live range can still split + n->outcnt() == 1 && // and use must be in this block + _cfg.get_block_for_node(n->unique_out()) == b) { + + Node* single_use = n->unique_out(); + assert(b->find_node(single_use) >= next_inst, "Use must be later in block"); + // Use can be earlier in block if it is a Phi, but then I should be a MultiDef + + // Find first non SpillCopy 'm' that follows the current instruction + // (current_inst - 1) is index for current instruction 'n' + Node* m = n; + for (uint i = next_inst; i <= last_inst && m->is_SpillCopy(); ++i) { + m = b->get_node(i); + } + if (m == single_use) { + lrg._area = 0.0; + } + } +} + +/* + * Copies do not define a new value and so do not interfere. + * Remove the copies source from the liveout set before interfering. + */ +void PhaseChaitin::remove_interference_from_copy(Block* b, uint location, uint lid_copy, IndexSet* liveout, double cost, Pressure& int_pressure, Pressure& float_pressure) { + if (liveout->remove(lid_copy)) { + LRG& lrg_copy = lrgs(lid_copy); + lrg_copy._area -= cost; + + // Lower register pressure since copy and definition can share the same register + lower_pressure(b, location, lrg_copy, liveout, int_pressure, float_pressure); + } +} + +/* + * The defined value must go in a particular register. Remove that register from + * all conflicting parties and avoid the interference. + */ +void PhaseChaitin::remove_bound_register_from_interfering_live_ranges(LRG& lrg, IndexSet* liveout, uint& must_spill) { + // Check for common case + const RegMask& rm = lrg.mask(); + int r_size = lrg.num_regs(); + // Smear odd bits + IndexSetIterator elements(liveout); + uint l = elements.next(); + while (l != 0) { + LRG& interfering_lrg = lrgs(l); + // If 'l' must spill already, do not further hack his bits. + // He'll get some interferences and be forced to spill later. + if (interfering_lrg._must_spill) { + l = elements.next(); + continue; + } + + // Remove bound register(s) from 'l's choices + RegMask old = interfering_lrg.mask(); + uint old_size = interfering_lrg.mask_size(); + + // Remove the bits from LRG 'rm' from LRG 'l' so 'l' no + // longer interferes with 'rm'. If 'l' requires aligned + // adjacent pairs, subtract out bit pairs. + assert(!interfering_lrg._is_vector || !interfering_lrg._fat_proj, "sanity"); + + if (interfering_lrg.num_regs() > 1 && !interfering_lrg._fat_proj) { + RegMask r2mask = rm; + // Leave only aligned set of bits. + r2mask.smear_to_sets(interfering_lrg.num_regs()); + // It includes vector case. + interfering_lrg.SUBTRACT(r2mask); + interfering_lrg.compute_set_mask_size(); + } else if (r_size != 1) { + // fat proj + interfering_lrg.SUBTRACT(rm); + interfering_lrg.compute_set_mask_size(); + } else { + // Common case: size 1 bound removal + OptoReg::Name r_reg = rm.find_first_elem(); + if (interfering_lrg.mask().Member(r_reg)) { + interfering_lrg.Remove(r_reg); + interfering_lrg.set_mask_size(interfering_lrg.mask().is_AllStack() ? LRG::AllStack_size : old_size - 1); + } + } + + // If 'l' goes completely dry, it must spill. + if (interfering_lrg.not_free()) { + // Give 'l' some kind of reasonable mask, so it picks up + // interferences (and will spill later). + interfering_lrg.set_mask(old); + interfering_lrg.set_mask_size(old_size); + must_spill++; + interfering_lrg._must_spill = 1; + interfering_lrg.set_reg(OptoReg::Name(LRG::SPILL_REG)); + } + l = elements.next(); + } +} + +/* + * Start loop at 1 (skip control edge) for most Nodes. SCMemProj's might be the + * sole use of a StoreLConditional. While StoreLConditionals set memory (the + * SCMemProj use) they also def flags; if that flag def is unused the allocator + * sees a flag-setting instruction with no use of the flags and assumes it's + * dead. This keeps the (useless) flag-setting behavior alive while also + * keeping the (useful) memory update effect. + */ +void PhaseChaitin::add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, double cost, Pressure& int_pressure, Pressure& float_pressure) { + JVMState* jvms = n->jvms(); + uint debug_start = jvms ? jvms->debug_start() : 999999; + + for (uint k = ((n->Opcode() == Op_SCMemProj) ? 0:1); k < n->req(); k++) { + Node* def = n->in(k); + uint lid = _lrg_map.live_range_id(def); + if (!lid) { + continue; + } + LRG& lrg = lrgs(lid); + + // No use-side cost for spilling debug info + if (k < debug_start) { + // A USE costs twice block frequency (once for the Load, once + // for a Load-delay). Rematerialized uses only cost once. + lrg._cost += (def->rematerialize() ? b->_freq : (b->_freq * 2)); + } + + if (liveout->insert(lid)) { + // Newly live things assumed live from here to top of block + lrg._area += cost; + raise_pressure(b, lrg, int_pressure, float_pressure); + assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); + } + assert(!(lrg._area < 0.0), "negative spill area" ); + } +} + +/* + * If we run off the top of the block with high pressure just record that the + * whole block is high pressure. (Even though we might have a transition + * lower down in the block) + */ +void PhaseChaitin::check_for_high_pressure_block(Pressure& pressure) { + // current pressure now means the pressure before the first instruction in the block + // (since we have stepped through all instructions backwards) + if (pressure._current_pressure > pressure._high_pressure_limit) { + pressure._high_pressure_index = 0; + } +} + +/* + * Compute high pressure indice; avoid landing in the middle of projnodes + * and set the high pressure index for the block + */ +void PhaseChaitin::adjust_high_pressure_index(Block* b, uint& block_hrp_index, Pressure& pressure) { + uint i = pressure._high_pressure_index; + if (i < b->number_of_nodes() && i < b->end_idx() + 1) { + Node* cur = b->get_node(i); + while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { + cur = b->get_node(--i); + } + } + block_hrp_index = i; +} + +/* Build an interference graph: + * That is, if 2 live ranges are simultaneously alive but in their acceptable + * register sets do not overlap, then they do not interfere. The IFG is built + * by a single reverse pass over each basic block. Starting with the known + * live-out set, we remove things that get defined and add things that become + * live (essentially executing one pass of a standard LIVE analysis). Just + * before a Node defines a value (and removes it from the live-ness set) that + * value is certainly live. The defined value interferes with everything + * currently live. The value is then removed from the live-ness set and it's + * inputs are added to the live-ness set. + * Compute register pressure for each block: + * We store the biggest register pressure for each block and also the first + * low to high register pressure transition within the block (if any). + */ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { - NOT_PRODUCT( Compile::TracePhase t3("buildIFG", &_t_buildIFGphysical, TimeCompiler); ) + NOT_PRODUCT(Compile::TracePhase t3("buildIFG", &_t_buildIFGphysical, TimeCompiler);) uint must_spill = 0; - - // For all blocks (in any order) do... for (uint i = 0; i < _cfg.number_of_blocks(); i++) { Block* block = _cfg.get_block(i); + // Clone (rather than smash in place) the liveout info, so it is alive // for the "collect_gc_info" phase later. IndexSet liveout(_live->live(block)); + + uint first_inst = first_nonphi_index(block); uint last_inst = block->end_idx(); - // Compute first nonphi node index - uint first_inst; - for (first_inst = 1; first_inst < last_inst; first_inst++) { - if (!block->get_node(first_inst)->is_Phi()) { - break; - } - } - // Spills could be inserted before CreateEx node which should be - // first instruction in block after Phis. Move CreateEx up. - for (uint insidx = first_inst; insidx < last_inst; insidx++) { - Node *ex = block->get_node(insidx); - if (ex->is_SpillCopy()) { - continue; - } - if (insidx > first_inst && ex->is_Mach() && ex->as_Mach()->ideal_Opcode() == Op_CreateEx) { - // If the CreateEx isn't above all the MachSpillCopies - // then move it to the top. - block->remove_node(insidx); - block->insert_node(ex, first_inst); - } - // Stop once a CreateEx or any other node is found - break; - } + move_exception_node_up(block, first_inst, last_inst); + + Pressure int_pressure(last_inst + 1, INTPRESSURE); + Pressure float_pressure(last_inst + 1, FLOATPRESSURE); + block->_reg_pressure = 0; + block->_freg_pressure = 0; - // Reset block's register pressure values for each ifg construction - uint pressure[2], hrp_index[2]; - pressure[0] = pressure[1] = 0; - hrp_index[0] = hrp_index[1] = last_inst+1; - block->_reg_pressure = block->_freg_pressure = 0; - // Liveout things are presumed live for the whole block. We accumulate - // 'area' accordingly. If they get killed in the block, we'll subtract - // the unused part of the block from the area. int inst_count = last_inst - first_inst; double cost = (inst_count <= 0) ? 0.0 : block->_freq * double(inst_count); assert(!(cost < 0.0), "negative spill cost" ); - IndexSetIterator elements(&liveout); - uint lidx; - while ((lidx = elements.next()) != 0) { - LRG &lrg = lrgs(lidx); - lrg._area += cost; - // Compute initial register pressure - if (lrg.mask().is_UP() && lrg.mask_size()) { - if (lrg._is_float || lrg._is_vector) { // Count float pressure - pressure[1] += lrg.reg_pressure(); - if (pressure[1] > block->_freg_pressure) { - block->_freg_pressure = pressure[1]; - } - // Count int pressure, but do not count the SP, flags - } else if(lrgs(lidx).mask().overlap(*Matcher::idealreg2regmask[Op_RegI])) { - pressure[0] += lrg.reg_pressure(); - if (pressure[0] > block->_reg_pressure) { - block->_reg_pressure = pressure[0]; - } - } - } - } - assert( pressure[0] == count_int_pressure (&liveout), "" ); - assert( pressure[1] == count_float_pressure(&liveout), "" ); - // The IFG is built by a single reverse pass over each basic block. - // Starting with the known live-out set, we remove things that get - // defined and add things that become live (essentially executing one - // pass of a standard LIVE analysis). Just before a Node defines a value - // (and removes it from the live-ness set) that value is certainly live. - // The defined value interferes with everything currently live. The - // value is then removed from the live-ness set and it's inputs are added - // to the live-ness set. - uint j; - for (j = last_inst + 1; j > 1; j--) { - Node* n = block->get_node(j - 1); + compute_initial_block_pressure(block, &liveout, int_pressure, float_pressure, cost); - // Get value being defined - uint r = _lrg_map.live_range_id(n); + for (uint location = last_inst; location > 0; location--) { + Node* n = block->get_node(location); + uint lid = _lrg_map.live_range_id(n); + + if(lid) { + LRG& lrg = lrgs(lid); - // Some special values do not allocate - if(r) { // A DEF normally costs block frequency; rematerialized values are // removed from the DEF sight, so LOWER costs here. - lrgs(r)._cost += n->rematerialize() ? 0 : block->_freq; + lrg._cost += n->rematerialize() ? 0 : block->_freq; - // If it is not live, then this instruction is dead. Probably caused - // by spilling and rematerialization. Who cares why, yank this baby. - if( !liveout.member(r) && n->Opcode() != Op_SafePoint ) { - Node *def = n->in(0); - if( !n->is_Proj() || - // Could also be a flags-projection of a dead ADD or such. - (_lrg_map.live_range_id(def) && !liveout.member(_lrg_map.live_range_id(def)))) { - block->remove_node(j - 1); - if (lrgs(r)._def == n) { - lrgs(r)._def = 0; - } - n->disconnect_inputs(NULL, C); - _cfg.unmap_node_from_block(n); - n->replace_by(C->top()); - // Since yanking a Node from block, high pressure moves up one - hrp_index[0]--; - hrp_index[1]--; + if (!liveout.member(lid) && n->Opcode() != Op_SafePoint) { + if (remove_node_if_not_used(block, location, n, lid, &liveout)) { + float_pressure._high_pressure_index--; + int_pressure._high_pressure_index--; continue; } - - // Fat-projections kill many registers which cannot be used to - // hold live ranges. - if (lrgs(r)._fat_proj) { - // Count the int-only registers - RegMask itmp = lrgs(r).mask(); - itmp.AND(*Matcher::idealreg2regmask[Op_RegI]); - int iregs = itmp.Size(); - if (pressure[0]+iregs > block->_reg_pressure) { - block->_reg_pressure = pressure[0] + iregs; - } - if (pressure[0] <= (uint)INTPRESSURE && pressure[0] + iregs > (uint)INTPRESSURE) { - hrp_index[0] = j - 1; - } - // Count the float-only registers - RegMask ftmp = lrgs(r).mask(); - ftmp.AND(*Matcher::idealreg2regmask[Op_RegD]); - int fregs = ftmp.Size(); - if (pressure[1] + fregs > block->_freg_pressure) { - block->_freg_pressure = pressure[1] + fregs; - } - if(pressure[1] <= (uint)FLOATPRESSURE && pressure[1]+fregs > (uint)FLOATPRESSURE) { - hrp_index[1] = j - 1; - } + if (lrg._fat_proj) { + check_for_high_pressure_transition_at_fatproj(block->_reg_pressure, location, lrg, int_pressure, Op_RegI); + check_for_high_pressure_transition_at_fatproj(block->_freg_pressure, location, lrg, float_pressure, Op_RegD); } + } else { + // A live range ends at its definition, remove the remaining area. + lrg._area -= cost; + assert(lrg._area >= 0.0, "negative spill area" ); - } else { // Else it is live - // A DEF also ends 'area' partway through the block. - lrgs(r)._area -= cost; - assert(!(lrgs(r)._area < 0.0), "negative spill area" ); + assign_high_score_to_immediate_copies(block, n, lrg, location + 1, last_inst); - // Insure high score for immediate-use spill copies so they get a color - if( n->is_SpillCopy() - && lrgs(r).is_singledef() // MultiDef live range can still split - && n->outcnt() == 1 // and use must be in this block - && _cfg.get_block_for_node(n->unique_out()) == block) { - // All single-use MachSpillCopy(s) that immediately precede their - // use must color early. If a longer live range steals their - // color, the spill copy will split and may push another spill copy - // further away resulting in an infinite spill-split-retry cycle. - // Assigning a zero area results in a high score() and a good - // location in the simplify list. - // - - Node *single_use = n->unique_out(); - assert(block->find_node(single_use) >= j, "Use must be later in block"); - // Use can be earlier in block if it is a Phi, but then I should be a MultiDef - - // Find first non SpillCopy 'm' that follows the current instruction - // (j - 1) is index for current instruction 'n' - Node *m = n; - for (uint i = j; i <= last_inst && m->is_SpillCopy(); ++i) { - m = block->get_node(i); - } - if (m == single_use) { - lrgs(r)._area = 0.0; - } + if (liveout.remove(lid)) { + lower_pressure(block, location, lrg, &liveout, int_pressure, float_pressure); } - - // Remove from live-out set - if( liveout.remove(r) ) { - // Adjust register pressure. - // Capture last hi-to-lo pressure transition - lower_pressure(&lrgs(r), j - 1, block, pressure, hrp_index); - assert( pressure[0] == count_int_pressure (&liveout), "" ); - assert( pressure[1] == count_float_pressure(&liveout), "" ); + uint copy_idx = n->is_Copy(); + if (copy_idx) { + uint lid_copy = _lrg_map.live_range_id(n->in(copy_idx)); + remove_interference_from_copy(block, location, lid_copy, &liveout, cost, int_pressure, float_pressure); } + } - // Copies do not define a new value and so do not interfere. - // Remove the copies source from the liveout set before interfering. - uint idx = n->is_Copy(); - if (idx) { - uint x = _lrg_map.live_range_id(n->in(idx)); - if (liveout.remove(x)) { - lrgs(x)._area -= cost; - // Adjust register pressure. - lower_pressure(&lrgs(x), j - 1, block, pressure, hrp_index); - assert( pressure[0] == count_int_pressure (&liveout), "" ); - assert( pressure[1] == count_float_pressure(&liveout), "" ); - } - } - } // End of if live or not - - // Interfere with everything live. If the defined value must - // go in a particular register, just remove that register from - // all conflicting parties and avoid the interference. - - // Make exclusions for rematerializable defs. Since rematerializable - // DEFs are not bound but the live range is, some uses must be bound. - // If we spill live range 'r', it can rematerialize at each use site - // according to its bindings. - const RegMask &rmask = lrgs(r).mask(); - if( lrgs(r).is_bound() && !(n->rematerialize()) && rmask.is_NotEmpty() ) { - // Check for common case - int r_size = lrgs(r).num_regs(); - OptoReg::Name r_reg = (r_size == 1) ? rmask.find_first_elem() : OptoReg::Physical; - // Smear odd bits - IndexSetIterator elements(&liveout); - uint l; - while ((l = elements.next()) != 0) { - LRG &lrg = lrgs(l); - // If 'l' must spill already, do not further hack his bits. - // He'll get some interferences and be forced to spill later. - if( lrg._must_spill ) continue; - // Remove bound register(s) from 'l's choices - RegMask old = lrg.mask(); - uint old_size = lrg.mask_size(); - // Remove the bits from LRG 'r' from LRG 'l' so 'l' no - // longer interferes with 'r'. If 'l' requires aligned - // adjacent pairs, subtract out bit pairs. - assert(!lrg._is_vector || !lrg._fat_proj, "sanity"); - if (lrg.num_regs() > 1 && !lrg._fat_proj) { - RegMask r2mask = rmask; - // Leave only aligned set of bits. - r2mask.smear_to_sets(lrg.num_regs()); - // It includes vector case. - lrg.SUBTRACT( r2mask ); - lrg.compute_set_mask_size(); - } else if( r_size != 1 ) { // fat proj - lrg.SUBTRACT( rmask ); - lrg.compute_set_mask_size(); - } else { // Common case: size 1 bound removal - if( lrg.mask().Member(r_reg) ) { - lrg.Remove(r_reg); - lrg.set_mask_size(lrg.mask().is_AllStack() ? LRG::AllStack_size : old_size - 1); - } - } - // If 'l' goes completely dry, it must spill. - if( lrg.not_free() ) { - // Give 'l' some kind of reasonable mask, so he picks up - // interferences (and will spill later). - lrg.set_mask( old ); - lrg.set_mask_size(old_size); - must_spill++; - lrg._must_spill = 1; - lrg.set_reg(OptoReg::Name(LRG::SPILL_REG)); - } - } - } // End of if bound - - // Now interference with everything that is live and has - // compatible register sets. - interfere_with_live(r,&liveout); - - } // End of if normal register-allocated value + // Since rematerializable DEFs are not bound but the live range is, + // some uses must be bound. If we spill live range 'r', it can + // rematerialize at each use site according to its bindings. + if (lrg.is_bound() && !n->rematerialize() && lrg.mask().is_NotEmpty()) { + remove_bound_register_from_interfering_live_ranges(lrg, &liveout, must_spill); + } + interfere_with_live(lid, &liveout); + } // Area remaining in the block inst_count--; cost = (inst_count <= 0) ? 0.0 : block->_freq * double(inst_count); - // Make all inputs live - if( !n->is_Phi() ) { // Phi function uses come from prior block - JVMState* jvms = n->jvms(); - uint debug_start = jvms ? jvms->debug_start() : 999999; - // Start loop at 1 (skip control edge) for most Nodes. - // SCMemProj's might be the sole use of a StoreLConditional. - // While StoreLConditionals set memory (the SCMemProj use) - // they also def flags; if that flag def is unused the - // allocator sees a flag-setting instruction with no use of - // the flags and assumes it's dead. This keeps the (useless) - // flag-setting behavior alive while also keeping the (useful) - // memory update effect. - for (uint k = ((n->Opcode() == Op_SCMemProj) ? 0:1); k < n->req(); k++) { - Node *def = n->in(k); - uint x = _lrg_map.live_range_id(def); - if (!x) { - continue; - } - LRG &lrg = lrgs(x); - // No use-side cost for spilling debug info - if (k < debug_start) { - // A USE costs twice block frequency (once for the Load, once - // for a Load-delay). Rematerialized uses only cost once. - lrg._cost += (def->rematerialize() ? block->_freq : (block->_freq + block->_freq)); - } - // It is live now - if (liveout.insert(x)) { - // Newly live things assumed live from here to top of block - lrg._area += cost; - // Adjust register pressure - if (lrg.mask().is_UP() && lrg.mask_size()) { - if (lrg._is_float || lrg._is_vector) { - pressure[1] += lrg.reg_pressure(); - if (pressure[1] > block->_freg_pressure) { - block->_freg_pressure = pressure[1]; - } - } else if( lrg.mask().overlap(*Matcher::idealreg2regmask[Op_RegI]) ) { - pressure[0] += lrg.reg_pressure(); - if (pressure[0] > block->_reg_pressure) { - block->_reg_pressure = pressure[0]; - } - } - } - assert( pressure[0] == count_int_pressure (&liveout), "" ); - assert( pressure[1] == count_float_pressure(&liveout), "" ); - } - assert(!(lrg._area < 0.0), "negative spill area" ); - } - } - } // End of reverse pass over all instructions in block - - // If we run off the top of the block with high pressure and - // never see a hi-to-low pressure transition, just record that - // the whole block is high pressure. - if (pressure[0] > (uint)INTPRESSURE) { - hrp_index[0] = 0; - if (pressure[0] > block->_reg_pressure) { - block->_reg_pressure = pressure[0]; - } - } - if (pressure[1] > (uint)FLOATPRESSURE) { - hrp_index[1] = 0; - if (pressure[1] > block->_freg_pressure) { - block->_freg_pressure = pressure[1]; + if (!n->is_Phi()) { + add_input_to_liveout(block, n, &liveout, cost, int_pressure, float_pressure); } } - // Compute high pressure indice; avoid landing in the middle of projnodes - j = hrp_index[0]; - if (j < block->number_of_nodes() && j < block->end_idx() + 1) { - Node* cur = block->get_node(j); - while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { - j--; - cur = block->get_node(j); - } - } - block->_ihrp_index = j; - j = hrp_index[1]; - if (j < block->number_of_nodes() && j < block->end_idx() + 1) { - Node* cur = block->get_node(j); - while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { - j--; - cur = block->get_node(j); - } - } - block->_fhrp_index = j; + check_for_high_pressure_block(int_pressure); + check_for_high_pressure_block(float_pressure); + adjust_high_pressure_index(block, block->_ihrp_index, int_pressure); + adjust_high_pressure_index(block, block->_fhrp_index, float_pressure); + // set the final_pressure as the register pressure for the block + block->_reg_pressure = int_pressure._final_pressure; + block->_freg_pressure = float_pressure._final_pressure; #ifndef PRODUCT // Gather Register Pressure Statistics - if( PrintOptoStatistics ) { - if (block->_reg_pressure > (uint)INTPRESSURE || block->_freg_pressure > (uint)FLOATPRESSURE) { + if (PrintOptoStatistics) { + if (block->_reg_pressure > int_pressure._high_pressure_limit || block->_freg_pressure > float_pressure._high_pressure_limit) { _high_pressure++; } else { _low_pressure++; } } #endif - } // End of for all blocks + } return must_spill; } From c4642dd6d7ac342bd522d2448f73d69a485a7cb7 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 28 Jan 2014 10:19:45 -0800 Subject: [PATCH 108/265] 8029941: rollback changes in make/jprt.properties for embedded testing Cleanup changes merged by accident Reviewed-by: roland, dholmes --- hotspot/make/jprt.properties | 72 ------------------------------------ 1 file changed, 72 deletions(-) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index a0548f2b37f..9109ded6f98 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -329,81 +329,9 @@ jprt.my.linux.i586.test.targets.embedded = \ # The complete list of test targets for jprt # Note: no PPC or ARM tests at this stage -jprt.my.linux.armvfpsflt.test.targets.embedded = \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_default, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_CMS, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_G1, \ - linux_armvfpsflt_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ - linux_armvfpsflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC - -# QEMU Emulators for ARM VFP HFLT -jprt.my.linux.armvfphflt.test.targets.embedded = \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_default, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_CMS, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_G1, \ - linux_armvfphflt_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ - linux_armvfphflt_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC - -jprt.my.linux.ppc.test.targets.embedded = \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-scimark, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_default, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_SerialGC, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParallelGC, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParNewGC, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_CMS, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_G1, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-{c1|c2}-GCBasher_ParOldGC, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_default, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_SerialGC, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParallelGC, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParNewGC, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_CMS, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_G1, \ - linux_ppc_2.6-productEmb-{c1|c2}-GCOld_ParOldGC, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_default, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c2-jbb_default_nontiered, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParallelGC, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_CMS, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_G1, \ - linux_ppc_2.6-{productEmb|fastdebugEmb}-c1-jbb_ParOldGC jprt.test.targets.standard = \ ${jprt.my.linux.i586.test.targets.embedded}, \ - ${jprt.my.linux.armvfpsflt.test.targets.embedded}, \ - ${jprt.my.linux.armvfphflt.test.targets.embedded}, \ - ${jprt.my.linux.ppc.test.targets.embedded}, \ ${jprt.my.solaris.sparcv9.test.targets}, \ ${jprt.my.solaris.x64.test.targets}, \ ${jprt.my.linux.i586.test.targets}, \ From 240cdde43aac0c159a8b858b87738ac34ce9ba88 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:09:25 +0000 Subject: [PATCH 109/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/THIRD_PARTY_README +++ b/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From a63ece1a06034efc7d50f20c4016550900c2e7a2 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:09:33 +0000 Subject: [PATCH 110/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- corba/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corba/THIRD_PARTY_README b/corba/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/corba/THIRD_PARTY_README +++ b/corba/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 5159b7ce2055322e20b695c2684f5326629fc3d9 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:09:41 +0000 Subject: [PATCH 111/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- hotspot/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/THIRD_PARTY_README b/hotspot/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/hotspot/THIRD_PARTY_README +++ b/hotspot/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 8de9c0cf2ad112e31150fc5b58028d2c76cd8a54 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:09:49 +0000 Subject: [PATCH 112/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- jaxp/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaxp/THIRD_PARTY_README b/jaxp/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/jaxp/THIRD_PARTY_README +++ b/jaxp/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 7aa4592f6ec0d1913caa5fdda816a8bb35057b46 Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:09:55 +0000 Subject: [PATCH 113/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- jaxws/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaxws/THIRD_PARTY_README b/jaxws/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/jaxws/THIRD_PARTY_README +++ b/jaxws/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 49b3f8639b743965d2281f129d22663cb928e5fe Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:10:19 +0000 Subject: [PATCH 114/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- langtools/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/THIRD_PARTY_README b/langtools/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/langtools/THIRD_PARTY_README +++ b/langtools/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 4dc0e46cb24d246a5f8862a0585aeb9a55a9c65c Mon Sep 17 00:00:00 2001 From: Jeff Dinkins Date: Tue, 28 Jan 2014 20:10:23 +0000 Subject: [PATCH 115/265] 8032816: THIRDPARTYREADME LittleCMS preamble missing JRE 8 & JDK 8 Reviewed-by: lana --- nashorn/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nashorn/THIRD_PARTY_README b/nashorn/THIRD_PARTY_README index ba48858c28f..a93b35b994c 100644 --- a/nashorn/THIRD_PARTY_README +++ b/nashorn/THIRD_PARTY_README @@ -1400,7 +1400,7 @@ THE SOFTWARE. ------------------------------------------------------------------------------- %% This notice is provided with respect to Little CMS 2.4, which may be -included with OpenJDK 8. +included with JRE 8, JDK 8, and OpenJDK 8. --- begin of LICENSE --- From 70737b100f49f5222f7a8a8b4db56ad86937df86 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 29 Jan 2014 12:22:13 +0100 Subject: [PATCH 116/265] 8033117: PPC64: Adapt to 8002074: Support for AES on SPARC Implement missing function Matcher::pass_original_key_for_aes() in ppc64 ad file. Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/ppc.ad | 5 +++++ hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 173d5445139..cb1d75dc08b 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2143,6 +2143,11 @@ const bool Matcher::misaligned_vectors_ok() { return false; } +// PPC AES support not yet implemented +const bool Matcher::pass_original_key_for_aes() { + return false; +} + // RETURNS: whether this branch offset is short enough that a short // branch can be used. // diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 0fc3491531c..1cd4d295925 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -2052,6 +2052,10 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); + if (UseAESIntrinsics) { + guarantee(!UseAESIntrinsics, "not yet implemented."); + } + // PPC uses stubs for safefetch. generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, &StubRoutines::_safefetch32_fault_pc, From 455663f56eb08935d0d8793fcee26839e805e090 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Thu, 30 Jan 2014 09:41:45 +0100 Subject: [PATCH 117/265] 6656031: SA: jmap -permstat number of classes is off by 1 Reviewed-by: sla, dholmes --- .../classes/sun/jvm/hotspot/tools/ClassLoaderStats.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java index d2ea2db855d..a5fac511d18 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java @@ -103,11 +103,12 @@ public class ClassLoaderStats extends Tool { } SystemDictionary dict = VM.getVM().getSystemDictionary(); - dict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() { - public void visit(Klass k, Oop loader) { + dict.classesDo(new SystemDictionary.ClassVisitor() { + public void visit(Klass k) { if (! (k instanceof InstanceKlass)) { return; } + Oop loader = ((InstanceKlass) k).getClassLoader(); LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader) : bootstrapLoaderData; if (ld != null) { From 4c4b46e490a63bf70a5eed71d0393393e7eeebbb Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 30 Jan 2014 14:30:01 +0100 Subject: [PATCH 118/265] 8033168: PPC64: gcc 4.8 warning in output_c.cpp Fix warnings Reviewed-by: kvn --- hotspot/src/share/vm/adlc/output_c.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index f3d0747aa5e..c351ed323d2 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -2502,7 +2502,7 @@ void ArchDesc::defineSize(FILE *fp, InstructForm &inst) { fprintf(fp,"}\n\n"); } -// Emit late expand function. +// Emit postalloc expand function. void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { InsEncode *ins_encode = inst._insencode; @@ -2519,7 +2519,7 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { // for each parameter specified in the encoding. ins_encode->reset(); const char *ec_name = ins_encode->encode_class_iter(); - assert(ec_name != NULL, "late expand must specify an encoding"); + assert(ec_name != NULL, "Postalloc expand must specify an encoding."); EncClass *encoding = _encode->encClass(ec_name); if (encoding == NULL) { @@ -2532,11 +2532,11 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { ec_name, encoding->num_args()); } - fprintf(fp, " // Access to ins and operands for late expand.\n"); + fprintf(fp, " // Access to ins and operands for postalloc expand.\n"); const int buflen = 2000; - char idxbuf[buflen]; char *ib = idxbuf; sprintf(ib, ""); - char nbuf [buflen]; char *nb = nbuf; sprintf(nb, ""); - char opbuf [buflen]; char *ob = opbuf; sprintf(ob, ""); + char idxbuf[buflen]; char *ib = idxbuf; idxbuf[0] = '\0'; + char nbuf [buflen]; char *nb = nbuf; nbuf[0] = '\0'; + char opbuf [buflen]; char *ob = opbuf; opbuf[0] = '\0'; encoding->_parameter_type.reset(); encoding->_parameter_name.reset(); @@ -2554,7 +2554,7 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { // There is no operand for the constanttablebase. } else if (inst.is_noninput_operand(idx)) { globalAD->syntax_err(inst._linenum, - "In %s: you can not pass the non-input %s to a late expand encoding.\n", + "In %s: you can not pass the non-input %s to a postalloc expand encoding.\n", inst._ident, arg_name); } else { ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", @@ -2605,7 +2605,7 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { fprintf(fp, "}\n\n"); ec_name = ins_encode->encode_class_iter(); - assert(ec_name == NULL, "Late expand may only have one encoding."); + assert(ec_name == NULL, "Postalloc expand may only have one encoding."); } // defineEmit ----------------------------------------------------------------- From 97d55c801e4d833db53c92d2f0fd23da31a49621 Mon Sep 17 00:00:00 2001 From: Ron Durbin Date: Thu, 30 Jan 2014 14:12:22 -0800 Subject: [PATCH 119/265] 8027113: decouple the '-XXaltjvm=' option from the gamma launcher Decoupled the '-XXaltjvm=' option from the gamma launcher. Clearing the way for removing the remaining cruft associated with the previously removed gamma launcher. Reviewed-by: dcubed, dholmes --- hotspot/make/Makefile | 6 +-- hotspot/make/hotspot.script | 30 ++++++++++--- hotspot/src/os/bsd/vm/os_bsd.cpp | 14 +++--- hotspot/src/os/linux/vm/os_linux.cpp | 15 ++++--- hotspot/src/os/solaris/vm/os_solaris.cpp | 15 ++++--- hotspot/src/os/windows/vm/os_windows.cpp | 44 +++++++++---------- .../ProjectCreator/WinGammaPlatformVC10.java | 13 +++++- hotspot/src/share/vm/runtime/arguments.cpp | 35 +++++++-------- hotspot/src/share/vm/runtime/arguments.hpp | 10 ++--- 9 files changed, 105 insertions(+), 77 deletions(-) diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 581a5daae12..e313baef93a 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -557,11 +557,11 @@ $(JDK_IMAGE_DIR)/jre/lib/rt.jar: # Testing the built JVM -RUN_JVM=JAVA_HOME=$(JDK_IMPORT_PATH) $(JDK_IMPORT_PATH)/bin/java -d$(ARCH_DATA_MODEL) -Dsun.java.launcher=gamma +RUN_JVM=JAVA_HOME=$(JDK_IMPORT_PATH) $(JDK_IMPORT_PATH)/bin/java -d$(ARCH_DATA_MODEL) -XXaltjvm=$(ALTJVM_DIR) -Dsun.java.launcher.is_altjvm=true generic_test: @$(ECHO) "Running with: $(ALTJVM_DIR)" - @$(RUN_JVM) -XXaltjvm=$(ALTJVM_DIR) -Xinternalversion - @$(RUN_JVM) -XXaltjvm=$(ALTJVM_DIR) -showversion -help + @$(RUN_JVM) -Xinternalversion + @$(RUN_JVM) -showversion -help # C2 test targets test_product test_optimized test_fastdebug test_debug: diff --git a/hotspot/make/hotspot.script b/hotspot/make/hotspot.script index 9177f6efef8..331cf6b38d4 100644 --- a/hotspot/make/hotspot.script +++ b/hotspot/make/hotspot.script @@ -49,7 +49,7 @@ then GDB=gdb fi -# This is the name of the gdb binary to use +# This is the name of the dbx binary to use if [ ! "$DBX" ] then DBX=dbx @@ -68,9 +68,16 @@ EMACS=emacs # End of user changeable parameters ----------------------------------------- # +OS=`uname -s` + # Make sure the paths are fully specified, i.e. they must begin with /. REL_MYDIR=`dirname $0` MYDIR=`cd $REL_MYDIR && pwd` +case "$OS" in +CYGWIN*) + MYDIR=`cygpath -m "$MYDIR"` + ;; +esac # # Look whether the user wants to run inside gdb @@ -102,8 +109,17 @@ else JDK=@@JDK_IMPORT_PATH@@ fi -if [ "${JDK}" = "" ]; then - echo "Failed to find JDK. Either ALT_JAVA_HOME is not set or JDK_IMPORT_PATH is empty." +if [ "${JDK}" != "" ]; then + case "$OS" in + CYGWIN*) + JDK=`cygpath -m "$JDK"` + ;; + esac + +else + echo "Failed to find JDK." \ + "Either ALT_JAVA_HOME is not set or JDK_IMPORT_PATH is empty." + exit 1 fi # We will set the LD_LIBRARY_PATH as follows: @@ -120,7 +136,6 @@ SBP=${MYDIR}:${JRE}/lib/${ARCH} # Set up a suitable LD_LIBRARY_PATH or DYLD_LIBRARY_PATH -OS=`uname -s` if [ "${OS}" = "Darwin" ] then if [ -z "$DYLD_LIBRARY_PATH" ] @@ -141,7 +156,7 @@ else export LD_LIBRARY_PATH fi -JPARMS="-Dsun.java.launcher=gamma -XXaltjvm=$MYDIR $@ $JAVA_ARGS"; +JPARMS="-XXaltjvm=$MYDIR -Dsun.java.launcher.is_altjvm=true $@ $JAVA_ARGS"; # Locate the java launcher LAUNCHER=$JDK/bin/java @@ -152,6 +167,11 @@ fi GDBSRCDIR=$MYDIR BASEDIR=`cd $MYDIR/../../.. && pwd` +case "$OS" in +CYGWIN*) + BASEDIR=`cygpath -m "$BASEDIR"` + ;; +esac init_gdb() { # Create a gdb script in case we should run inside gdb diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 456daba559c..cadf960b1ac 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1788,12 +1788,14 @@ void os::jvm_path(char *buf, jint buflen) { if (rp == NULL) return; - if (Arguments::created_by_gamma_launcher()) { - // Support for the gamma launcher. Typical value for buf is - // "/jre/lib///libjvm". If "/jre/lib/" appears at - // the right place in the string, then assume we are installed in a JDK and - // we're done. Otherwise, check for a JAVA_HOME environment variable and - // construct a path to the JVM being overridden. + if (Arguments::sun_java_launcher_is_altjvm()) { + // Support for the java launcher's '-XXaltjvm=' option. Typical + // value for buf is "/jre/lib///libjvm.so" + // or "/jre/lib//libjvm.dylib". If "/jre/lib/" + // appears at the right place in the string, then assume we are + // installed in a JDK and we're done. Otherwise, check for a + // JAVA_HOME environment variable and construct a path to the JVM + // being overridden. const char *p = buf + strlen(buf) - 1; for (int count = 0; p > buf && count < 5; ++count) { diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d0751f005ad..1e3fc78b505 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2371,13 +2371,14 @@ void os::jvm_path(char *buf, jint buflen) { if (rp == NULL) return; - if (Arguments::created_by_gamma_launcher()) { - // Support for the gamma launcher. Typical value for buf is - // "/jre/lib///libjvm.so". If "/jre/lib/" appears at - // the right place in the string, then assume we are installed in a JDK and - // we're done. Otherwise, check for a JAVA_HOME environment variable and fix - // up the path so it looks like libjvm.so is installed there (append a - // fake suffix hotspot/libjvm.so). + if (Arguments::sun_java_launcher_is_altjvm()) { + // Support for the java launcher's '-XXaltjvm=' option. Typical + // value for buf is "/jre/lib///libjvm.so". + // If "/jre/lib/" appears at the right place in the string, then + // assume we are installed in a JDK and we're done. Otherwise, check + // for a JAVA_HOME environment variable and fix up the path so it + // looks like libjvm.so is installed there (append a fake suffix + // hotspot/libjvm.so). const char *p = buf + strlen(buf) - 1; for (int count = 0; p > buf && count < 5; ++count) { for (--p; p > buf && *p != '/'; --p) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 533bbb76650..396e9df542e 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2441,13 +2441,14 @@ void os::jvm_path(char *buf, jint buflen) { return; } - if (Arguments::created_by_gamma_launcher()) { - // Support for the gamma launcher. Typical value for buf is - // "/jre/lib///libjvm.so". If "/jre/lib/" appears at - // the right place in the string, then assume we are installed in a JDK and - // we're done. Otherwise, check for a JAVA_HOME environment variable and fix - // up the path so it looks like libjvm.so is installed there (append a - // fake suffix hotspot/libjvm.so). + if (Arguments::sun_java_launcher_is_altjvm()) { + // Support for the java launcher's '-XXaltjvm=' option. Typical + // value for buf is "/jre/lib///libjvm.so". + // If "/jre/lib/" appears at the right place in the string, then + // assume we are installed in a JDK and we're done. Otherwise, check + // for a JAVA_HOME environment variable and fix up the path so it + // looks like libjvm.so is installed there (append a fake suffix + // hotspot/libjvm.so). const char *p = buf + strlen(buf) - 1; for (int count = 0; p > buf && count < 5; ++count) { for (--p; p > buf && *p != '/'; --p) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 5cf47426595..2fa8269ee5e 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1810,32 +1810,30 @@ void os::jvm_path(char *buf, jint buflen) { } buf[0] = '\0'; - if (Arguments::created_by_gamma_launcher()) { - // Support for the gamma launcher. Check for an - // JAVA_HOME environment variable - // and fix up the path so it looks like - // libjvm.so is installed there (append a fake suffix - // hotspot/libjvm.so). - char* java_home_var = ::getenv("JAVA_HOME"); - if (java_home_var != NULL && java_home_var[0] != 0) { + if (Arguments::sun_java_launcher_is_altjvm()) { + // Support for the java launcher's '-XXaltjvm=' option. Check + // for a JAVA_HOME environment variable and fix up the path so it + // looks like jvm.dll is installed there (append a fake suffix + // hotspot/jvm.dll). + char* java_home_var = ::getenv("JAVA_HOME"); + if (java_home_var != NULL && java_home_var[0] != 0) { + strncpy(buf, java_home_var, buflen); - strncpy(buf, java_home_var, buflen); - - // determine if this is a legacy image or modules image - // modules image doesn't have "jre" subdirectory - size_t len = strlen(buf); - char* jrebin_p = buf + len; - jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\"); - if (0 != _access(buf, 0)) { - jio_snprintf(jrebin_p, buflen-len, "\\bin\\"); - } - len = strlen(buf); - jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll"); - } + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + size_t len = strlen(buf); + char* jrebin_p = buf + len; + jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\"); + if (0 != _access(buf, 0)) { + jio_snprintf(jrebin_p, buflen-len, "\\bin\\"); + } + len = strlen(buf); + jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll"); + } } - if(buf[0] == '\0') { - GetModuleFileName(vm_lib_handle, buf, buflen); + if (buf[0] == '\0') { + GetModuleFileName(vm_lib_handle, buf, buflen); } strcpy(saved_jvm_path, buf); } diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java index 6216a84adb1..0e0c846c318 100644 --- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java +++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java @@ -161,7 +161,18 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 { for (BuildConfig cfg : allConfigs) { startTag(cfg, "PropertyGroup"); tagData("LocalDebuggerCommand", cfg.get("JdkTargetRoot") + "\\bin\\java.exe"); - tagData("LocalDebuggerCommandArguments", "-XXaltjvm=$(TargetDir) -Dsun.java.launcher=gamma"); + // The JVM loads some libraries using a path relative to + // itself because it expects to be in a JRE or a JDK. The java + // launcher's '-XXaltjvm=' option allows the JVM to be outside + // the JRE or JDK so '-Dsun.java.launcher.is_altjvm=true' + // forces a fake JAVA_HOME relative path to be used to + // find the other libraries. The '-XX:+PauseAtExit' option + // causes the VM to wait for key press before exiting; this + // allows any stdout or stderr messages to be seen before + // the cmdtool exits. + tagData("LocalDebuggerCommandArguments", "-XXaltjvm=$(TargetDir) " + + "-Dsun.java.launcher.is_altjvm=true " + + "-XX:+UnlockDiagnosticVMOptions -XX:+PauseAtExit"); tagData("LocalDebuggerEnvironment", "JAVA_HOME=" + cfg.get("JdkTargetRoot")); endTag(); } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index e237ba00f0c..acd5c162c58 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -101,7 +101,7 @@ bool Arguments::_xdebug_mode = false; const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG; const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; -bool Arguments::_created_by_gamma_launcher = false; +bool Arguments::_sun_java_launcher_is_altjvm = false; // These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; @@ -151,7 +151,8 @@ static void logOption(const char* opt) { // Process java launcher properties. void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) { - // See if sun.java.launcher or sun.java.launcher.pid is defined. + // See if sun.java.launcher, sun.java.launcher.is_altjvm or + // sun.java.launcher.pid is defined. // Must do this before setting up other system properties, // as some of them may depend on launcher type. for (int index = 0; index < args->nOptions; index++) { @@ -162,6 +163,12 @@ void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) { process_java_launcher_argument(tail, option->extraInfo); continue; } + if (match_option(option, "-Dsun.java.launcher.is_altjvm=", &tail)) { + if (strcmp(tail, "true") == 0) { + _sun_java_launcher_is_altjvm = true; + } + continue; + } if (match_option(option, "-Dsun.java.launcher.pid=", &tail)) { _sun_java_launcher_pid = atoi(tail); continue; @@ -1013,9 +1020,10 @@ bool Arguments::add_property(const char* prop) { _java_command = value; // Record value in Arguments, but let it get passed to Java. - } else if (strcmp(key, "sun.java.launcher.pid") == 0) { - // launcher.pid property is private and is processed - // in process_sun_java_launcher_properties(); + } else if (strcmp(key, "sun.java.launcher.is_altjvm") == 0 || + strcmp(key, "sun.java.launcher.pid") == 0) { + // sun.java.launcher.is_altjvm and sun.java.launcher.pid property are + // private and are processed in process_sun_java_launcher_properties(); // the sun.java.launcher property is passed on to the java application FreeHeap(key); if (eq != NULL) { @@ -1800,9 +1808,6 @@ void Arguments::process_java_compiler_argument(char* arg) { void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { _sun_java_launcher = strdup(launcher); - if (strcmp("gamma", _sun_java_launcher) == 0) { - _created_by_gamma_launcher = true; - } } bool Arguments::created_by_java_launcher() { @@ -1810,8 +1815,8 @@ bool Arguments::created_by_java_launcher() { return strcmp(DEFAULT_JAVA_LAUNCHER, _sun_java_launcher) != 0; } -bool Arguments::created_by_gamma_launcher() { - return _created_by_gamma_launcher; +bool Arguments::sun_java_launcher_is_altjvm() { + return _sun_java_launcher_is_altjvm; } //=========================================================================================================== @@ -3765,16 +3770,6 @@ jint Arguments::apply_ergo() { } } - // set PauseAtExit if the gamma launcher was used and a debugger is attached - // but only if not already set on the commandline - if (Arguments::created_by_gamma_launcher() && os::is_debugger_attached()) { - bool set = false; - CommandLineFlags::wasSetOnCmdline("PauseAtExit", &set); - if (!set) { - FLAG_SET_DEFAULT(PauseAtExit, true); - } - } - return JNI_OK; } diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index d016e22f22e..65dd0711a61 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -268,14 +268,14 @@ class Arguments : AllStatic { static const char* _java_vendor_url_bug; // sun.java.launcher, private property to provide information about - // java/gamma launcher + // java launcher static const char* _sun_java_launcher; // sun.java.launcher.pid, private property static int _sun_java_launcher_pid; - // was this VM created by the gamma launcher - static bool _created_by_gamma_launcher; + // was this VM created via the -XXaltjvm= option + static bool _sun_java_launcher_is_altjvm; // Option flags static bool _has_profile; @@ -483,8 +483,8 @@ class Arguments : AllStatic { static const char* sun_java_launcher() { return _sun_java_launcher; } // Was VM created by a Java launcher? static bool created_by_java_launcher(); - // Was VM created by the gamma Java launcher? - static bool created_by_gamma_launcher(); + // -Dsun.java.launcher.is_altjvm + static bool sun_java_launcher_is_altjvm(); // -Dsun.java.launcher.pid static int sun_java_launcher_pid() { return _sun_java_launcher_pid; } From eaac73cf8426c61917df515a34f4cb4b6b75eb25 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Mon, 3 Feb 2014 13:41:26 +0100 Subject: [PATCH 120/265] 8032462: Change the linux SDT implementation to use USDT2 instead of USDT1 Reviewed-by: coleenp, sspitsyn, kamg --- hotspot/make/bsd/makefiles/dtrace.make | 13 +- hotspot/make/linux/makefiles/buildtree.make | 12 +- hotspot/make/linux/makefiles/dtrace.make | 33 +- hotspot/make/linux/makefiles/top.make | 5 +- hotspot/make/solaris/makefiles/dtrace.make | 17 +- hotspot/src/os/bsd/dtrace/hs_private.d | 40 -- .../src/os/{bsd => posix}/dtrace/hotspot.d | 0 .../os/{bsd => posix}/dtrace/hotspot_jni.d | 0 .../os/{solaris => posix}/dtrace/hs_private.d | 0 hotspot/src/os/solaris/dtrace/hotspot.d | 86 --- hotspot/src/os/solaris/dtrace/hotspot_jni.d | 506 ------------------ hotspot/src/share/vm/utilities/dtrace.hpp | 14 +- 12 files changed, 64 insertions(+), 662 deletions(-) delete mode 100644 hotspot/src/os/bsd/dtrace/hs_private.d rename hotspot/src/os/{bsd => posix}/dtrace/hotspot.d (100%) rename hotspot/src/os/{bsd => posix}/dtrace/hotspot_jni.d (100%) rename hotspot/src/os/{solaris => posix}/dtrace/hs_private.d (100%) delete mode 100644 hotspot/src/os/solaris/dtrace/hotspot.d delete mode 100644 hotspot/src/os/solaris/dtrace/hotspot_jni.d diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make index 7bef4f8a616..c13672aed16 100644 --- a/hotspot/make/bsd/makefiles/dtrace.make +++ b/hotspot/make/bsd/makefiles/dtrace.make @@ -53,6 +53,7 @@ JVMOFFS.o = $(JVMOFFS).o GENOFFS = generate$(JVMOFFS) DTRACE_SRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/dtrace +DTRACE_COMMON_SRCDIR = $(GAMMADIR)/src/os/posix/dtrace DTRACE = dtrace DTRACE.o = $(DTRACE).o @@ -262,14 +263,14 @@ endif $(DtraceOutDir): mkdir $(DtraceOutDir) -$(DtraceOutDir)/hotspot.h: $(DTRACE_SRCDIR)/hotspot.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot.d +$(DtraceOutDir)/hotspot.h: $(DTRACE_COMMON_SRCDIR)/hotspot.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot.d -$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot_jni.d +$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d -$(DtraceOutDir)/hs_private.h: $(DTRACE_SRCDIR)/hs_private.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hs_private.d +$(DtraceOutDir)/hs_private.h: $(DTRACE_COMMON_SRCDIR)/hs_private.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hs_private.d dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index fd6c52513fe..67ef0e35d6c 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -124,7 +124,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make -BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make trace.make sa.make dtrace.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -361,6 +361,16 @@ sa.make: $(BUILDTREE_MAKE) echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ +dtrace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + FORCE: .PHONY: all FORCE diff --git a/hotspot/make/linux/makefiles/dtrace.make b/hotspot/make/linux/makefiles/dtrace.make index b50eab183de..3a053736aae 100644 --- a/hotspot/make/linux/makefiles/dtrace.make +++ b/hotspot/make/linux/makefiles/dtrace.make @@ -42,18 +42,39 @@ ifneq ($(ALT_SDT_H),) else SDT_H_FILE = /usr/include/sys/sdt.h endif + DTRACE_ENABLED = $(shell test -f $(SDT_H_FILE) && echo $(SDT_H_FILE)) REASON = "$(SDT_H_FILE) not found" -ifneq ($(DTRACE_ENABLED),) - CFLAGS += -DDTRACE_ENABLED -endif +endif # GCC version +endif # OPENJDK -endif + +DTRACE_COMMON_SRCDIR = $(GAMMADIR)/src/os/posix/dtrace +DTRACE_PROG = dtrace +DtraceOutDir = $(GENERATED)/dtracefiles + +$(DtraceOutDir): + mkdir $(DtraceOutDir) + +$(DtraceOutDir)/hotspot.h: $(DTRACE_COMMON_SRCDIR)/hotspot.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot.d + +$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d + +$(DtraceOutDir)/hs_private.h: $(DTRACE_COMMON_SRCDIR)/hs_private.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hs_private.d + +ifneq ($(DTRACE_ENABLED),) +CFLAGS += -DDTRACE_ENABLED +dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h +else +dtrace_gen_headers: + $(QUIETLY) echo "**NOTICE** Dtrace support disabled: $(REASON)" endif # Phony target used in vm.make build target to check whether enabled. -.PHONY: dtraceCheck ifeq ($(DTRACE_ENABLED),) dtraceCheck: $(QUIETLY) echo "**NOTICE** Dtrace support disabled: $(REASON)" @@ -61,5 +82,7 @@ else dtraceCheck: endif +.PHONY: dtrace_gen_headers dtraceCheck + # It doesn't support HAVE_DTRACE_H though. diff --git a/hotspot/make/linux/makefiles/top.make b/hotspot/make/linux/makefiles/top.make index 95e6e6856e8..8c6c2ca0194 100644 --- a/hotspot/make/linux/makefiles/top.make +++ b/hotspot/make/linux/makefiles/top.make @@ -80,7 +80,7 @@ default: vm_build_preliminaries the_vm @echo All done. # This is an explicit dependency for the sake of parallel makes. -vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) trace_stuff jvmti_stuff sa_stuff +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) trace_stuff jvmti_stuff sa_stuff dtrace_stuff @# We need a null action here, so implicit rules don't get consulted. $(Cached_plat): $(Plat_File) @@ -102,6 +102,9 @@ trace_stuff: jvmti_stuff $(Cached_plat) $(adjust-mflags) sa_stuff: @$(MAKE) -f sa.make $(MFLAGS-adjusted) +dtrace_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f dtrace.make dtrace_gen_headers $(MFLAGS-adjusted) GENERATED=$(GENERATED) + # and the VM: must use other makefile with dependencies included # We have to go to great lengths to get control over the -jN argument diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 3b32385ecad..5af625b54db 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -55,6 +55,7 @@ JVMOFFS.o = $(JVMOFFS).o GENOFFS = generate$(JVMOFFS) DTRACE_SRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/dtrace +DTRACE_COMMON_SRCDIR = $(GAMMADIR)/src/os/posix/dtrace DTRACE = dtrace DTRACE.o = $(DTRACE).o @@ -253,8 +254,8 @@ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) endif endif -$(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \ - $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d +$(DTRACE).d: $(DTRACE_COMMON_SRCDIR)/hotspot.d $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d \ + $(DTRACE_COMMON_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d $(QUIETLY) cat $^ > $@ DTraced_Files = ciEnv.o \ @@ -332,14 +333,14 @@ $(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files) $(DtraceOutDir): mkdir $(DtraceOutDir) -$(DtraceOutDir)/hotspot.h: $(DTRACE_SRCDIR)/hotspot.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot.d +$(DtraceOutDir)/hotspot.h: $(DTRACE_COMMON_SRCDIR)/hotspot.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot.d -$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot_jni.d +$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d -$(DtraceOutDir)/hs_private.h: $(DTRACE_SRCDIR)/hs_private.d | $(DtraceOutDir) - $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hs_private.d +$(DtraceOutDir)/hs_private.h: $(DTRACE_COMMON_SRCDIR)/hs_private.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hs_private.d dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h diff --git a/hotspot/src/os/bsd/dtrace/hs_private.d b/hotspot/src/os/bsd/dtrace/hs_private.d deleted file mode 100644 index 50f4264a3c1..00000000000 --- a/hotspot/src/os/bsd/dtrace/hs_private.d +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -provider hs_private { - probe hashtable__new_entry(void*, uint32_t, uintptr_t, void*); - probe safepoint__begin(); - probe safepoint__end(); - probe cms__initmark__begin(); - probe cms__initmark__end(); - probe cms__remark__begin(); - probe cms__remark__end(); -}; - -#pragma D attributes Private/Private/Common provider hs_private provider -#pragma D attributes Private/Private/Unknown provider hs_private module -#pragma D attributes Private/Private/Unknown provider hs_private function -#pragma D attributes Private/Private/Common provider hs_private name -#pragma D attributes Private/Private/Common provider hs_private args - diff --git a/hotspot/src/os/bsd/dtrace/hotspot.d b/hotspot/src/os/posix/dtrace/hotspot.d similarity index 100% rename from hotspot/src/os/bsd/dtrace/hotspot.d rename to hotspot/src/os/posix/dtrace/hotspot.d diff --git a/hotspot/src/os/bsd/dtrace/hotspot_jni.d b/hotspot/src/os/posix/dtrace/hotspot_jni.d similarity index 100% rename from hotspot/src/os/bsd/dtrace/hotspot_jni.d rename to hotspot/src/os/posix/dtrace/hotspot_jni.d diff --git a/hotspot/src/os/solaris/dtrace/hs_private.d b/hotspot/src/os/posix/dtrace/hs_private.d similarity index 100% rename from hotspot/src/os/solaris/dtrace/hs_private.d rename to hotspot/src/os/posix/dtrace/hs_private.d diff --git a/hotspot/src/os/solaris/dtrace/hotspot.d b/hotspot/src/os/solaris/dtrace/hotspot.d deleted file mode 100644 index b3679eaba62..00000000000 --- a/hotspot/src/os/solaris/dtrace/hotspot.d +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -provider hotspot { - probe class__loaded(char*, uintptr_t, void*, uintptr_t); - probe class__unloaded(char*, uintptr_t, void*, uintptr_t); - probe class__initialization__required(char*, uintptr_t, void*, intptr_t); - probe class__initialization__recursive(char*, uintptr_t, void*, intptr_t,int); - probe class__initialization__concurrent(char*, uintptr_t, void*, intptr_t,int); - probe class__initialization__erroneous(char*, uintptr_t, void*, intptr_t, int); - probe class__initialization__super__failed(char*, uintptr_t, void*, intptr_t,int); - probe class__initialization__clinit(char*, uintptr_t, void*, intptr_t,int); - probe class__initialization__error(char*, uintptr_t, void*, intptr_t,int); - probe class__initialization__end(char*, uintptr_t, void*, intptr_t,int); - probe vm__init__begin(); - probe vm__init__end(); - probe vm__shutdown(); - probe vmops__request(char*, uintptr_t, int); - probe vmops__begin(char*, uintptr_t, int); - probe vmops__end(char*, uintptr_t, int); - probe gc__begin(uintptr_t); - probe gc__end(); - probe mem__pool__gc__begin( - char*, uintptr_t, char*, uintptr_t, - uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe mem__pool__gc__end( - char*, uintptr_t, char*, uintptr_t, - uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe thread__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe thread__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe thread__sleep__begin(long long); - probe thread__sleep__end(int); - probe thread__yield(); - probe thread__park__begin(uintptr_t, int, long long); - probe thread__park__end(uintptr_t); - probe thread__unpark(uintptr_t); - probe method__compile__begin( - char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, char*, uintptr_t); - probe method__compile__end( - char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, - char*, uintptr_t, uintptr_t); - probe compiled__method__load( - char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, void*, uintptr_t); - probe compiled__method__unload( - char*, uintptr_t, char*, uintptr_t, char*, uintptr_t); - probe monitor__contended__enter(uintptr_t, uintptr_t, char*, uintptr_t); - probe monitor__contended__entered(uintptr_t, uintptr_t, char*, uintptr_t); - probe monitor__contended__exit(uintptr_t, uintptr_t, char*, uintptr_t); - probe monitor__wait(uintptr_t, uintptr_t, char*, uintptr_t, uintptr_t); - probe monitor__waited(uintptr_t, uintptr_t, char*, uintptr_t); - probe monitor__notify(uintptr_t, uintptr_t, char*, uintptr_t); - probe monitor__notifyAll(uintptr_t, uintptr_t, char*, uintptr_t); - - probe object__alloc(int, char*, uintptr_t, uintptr_t); - probe method__entry( - int, char*, int, char*, int, char*, int); - probe method__return( - int, char*, int, char*, int, char*, int); -}; - -#pragma D attributes Evolving/Evolving/Common provider hotspot provider -#pragma D attributes Private/Private/Unknown provider hotspot module -#pragma D attributes Private/Private/Unknown provider hotspot function -#pragma D attributes Evolving/Evolving/Common provider hotspot name -#pragma D attributes Evolving/Evolving/Common provider hotspot args diff --git a/hotspot/src/os/solaris/dtrace/hotspot_jni.d b/hotspot/src/os/solaris/dtrace/hotspot_jni.d deleted file mode 100644 index cca1c517650..00000000000 --- a/hotspot/src/os/solaris/dtrace/hotspot_jni.d +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -provider hotspot_jni { - probe AllocObject__entry(void*, void*); - probe AllocObject__return(void*); - probe AttachCurrentThreadAsDaemon__entry(void*, void**, void*); - probe AttachCurrentThreadAsDaemon__return(uint32_t); - probe AttachCurrentThread__entry(void*, void**, void*); - probe AttachCurrentThread__return(uint32_t); - probe CallBooleanMethodA__entry(void*, void*, uintptr_t); - probe CallBooleanMethodA__return(uintptr_t); - probe CallBooleanMethod__entry(void*, void*, uintptr_t); - probe CallBooleanMethod__return(uintptr_t); - probe CallBooleanMethodV__entry(void*, void*, uintptr_t); - probe CallBooleanMethodV__return(uintptr_t); - probe CallByteMethodA__entry(void*, void*, uintptr_t); - probe CallByteMethodA__return(char); - probe CallByteMethod__entry(void*, void*, uintptr_t); - probe CallByteMethod__return(char); - probe CallByteMethodV__entry(void*, void*, uintptr_t); - probe CallByteMethodV__return(char); - probe CallCharMethodA__entry(void*, void*, uintptr_t); - probe CallCharMethodA__return(uint16_t); - probe CallCharMethod__entry(void*, void*, uintptr_t); - probe CallCharMethod__return(uint16_t); - probe CallCharMethodV__entry(void*, void*, uintptr_t); - probe CallCharMethodV__return(uint16_t); - probe CallDoubleMethodA__entry(void*, void*, uintptr_t); - probe CallDoubleMethodA__return(); - probe CallDoubleMethod__entry(void*, void*, uintptr_t); - probe CallDoubleMethod__return(); - probe CallDoubleMethodV__entry(void*, void*, uintptr_t); - probe CallDoubleMethodV__return(); - probe CallFloatMethodA__entry(void*, void*, uintptr_t); - probe CallFloatMethodA__return(); - probe CallFloatMethod__entry(void*, void*, uintptr_t); - probe CallFloatMethod__return(); - probe CallFloatMethodV__entry(void*, void*, uintptr_t); - probe CallFloatMethodV__return(); - probe CallIntMethodA__entry(void*, void*, uintptr_t); - probe CallIntMethodA__return(uint32_t); - probe CallIntMethod__entry(void*, void*, uintptr_t); - probe CallIntMethod__return(uint32_t); - probe CallIntMethodV__entry(void*, void*, uintptr_t); - probe CallIntMethodV__return(uint32_t); - probe CallLongMethodA__entry(void*, void*, uintptr_t); - probe CallLongMethodA__return(uintptr_t); - probe CallLongMethod__entry(void*, void*, uintptr_t); - probe CallLongMethod__return(uintptr_t); - probe CallLongMethodV__entry(void*, void*, uintptr_t); - probe CallLongMethodV__return(uintptr_t); - probe CallNonvirtualBooleanMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualBooleanMethodA__return(uintptr_t); - probe CallNonvirtualBooleanMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualBooleanMethod__return(uintptr_t); - probe CallNonvirtualBooleanMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualBooleanMethodV__return(uintptr_t); - probe CallNonvirtualByteMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualByteMethodA__return(char); - probe CallNonvirtualByteMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualByteMethod__return(char); - probe CallNonvirtualByteMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualByteMethodV__return(char); - probe CallNonvirtualCharMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualCharMethodA__return(uint16_t); - probe CallNonvirtualCharMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualCharMethod__return(uint16_t); - probe CallNonvirtualCharMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualCharMethodV__return(uint16_t); - probe CallNonvirtualDoubleMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualDoubleMethodA__return(); - probe CallNonvirtualDoubleMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualDoubleMethod__return(); - probe CallNonvirtualDoubleMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualDoubleMethodV__return(); - probe CallNonvirtualFloatMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualFloatMethodA__return(); - probe CallNonvirtualFloatMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualFloatMethod__return(); - probe CallNonvirtualFloatMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualFloatMethodV__return(); - probe CallNonvirtualIntMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualIntMethodA__return(uint32_t); - probe CallNonvirtualIntMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualIntMethod__return(uint32_t); - probe CallNonvirtualIntMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualIntMethodV__return(uint32_t); - probe CallNonvirtualLongMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualLongMethodA__return(uintptr_t); - probe CallNonvirtualLongMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualLongMethod__return(uintptr_t); - probe CallNonvirtualLongMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualLongMethodV__return(uintptr_t); - probe CallNonvirtualObjectMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualObjectMethodA__return(void*); - probe CallNonvirtualObjectMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualObjectMethod__return(void*); - probe CallNonvirtualObjectMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualObjectMethodV__return(void*); - probe CallNonvirtualShortMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualShortMethodA__return(uint16_t); - probe CallNonvirtualShortMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualShortMethod__return(uint16_t); - probe CallNonvirtualShortMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualShortMethodV__return(uint16_t); - probe CallNonvirtualVoidMethodA__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualVoidMethodA__return(); - probe CallNonvirtualVoidMethod__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualVoidMethod__return(); - probe CallNonvirtualVoidMethodV__entry(void*, void*, void*, uintptr_t); - probe CallNonvirtualVoidMethodV__return(); - probe CallObjectMethodA__entry(void*, void*, uintptr_t); - probe CallObjectMethodA__return(void*); - probe CallObjectMethod__entry(void*, void*, uintptr_t); - probe CallObjectMethod__return(void*); - probe CallObjectMethodV__entry(void*, void*, uintptr_t); - probe CallObjectMethodV__return(void*); - probe CallShortMethodA__entry(void*, void*, uintptr_t); - probe CallShortMethodA__return(uint16_t); - probe CallShortMethod__entry(void*, void*, uintptr_t); - probe CallShortMethod__return(uint16_t); - probe CallShortMethodV__entry(void*, void*, uintptr_t); - probe CallShortMethodV__return(uint16_t); - probe CallStaticBooleanMethodA__entry(void*, void*, uintptr_t); - probe CallStaticBooleanMethodA__return(uintptr_t); - probe CallStaticBooleanMethod__entry(void*, void*, uintptr_t); - probe CallStaticBooleanMethod__return(uintptr_t); - probe CallStaticBooleanMethodV__entry(void*, void*, uintptr_t); - probe CallStaticBooleanMethodV__return(uintptr_t); - probe CallStaticByteMethodA__entry(void*, void*, uintptr_t); - probe CallStaticByteMethodA__return(char); - probe CallStaticByteMethod__entry(void*, void*, uintptr_t); - probe CallStaticByteMethod__return(char); - probe CallStaticByteMethodV__entry(void*, void*, uintptr_t); - probe CallStaticByteMethodV__return(char); - probe CallStaticCharMethodA__entry(void*, void*, uintptr_t); - probe CallStaticCharMethodA__return(uint16_t); - probe CallStaticCharMethod__entry(void*, void*, uintptr_t); - probe CallStaticCharMethod__return(uint16_t); - probe CallStaticCharMethodV__entry(void*, void*, uintptr_t); - probe CallStaticCharMethodV__return(uint16_t); - probe CallStaticDoubleMethodA__entry(void*, void*, uintptr_t); - probe CallStaticDoubleMethodA__return(); - probe CallStaticDoubleMethod__entry(void*, void*, uintptr_t); - probe CallStaticDoubleMethod__return(); - probe CallStaticDoubleMethodV__entry(void*, void*, uintptr_t); - probe CallStaticDoubleMethodV__return(); - probe CallStaticFloatMethodA__entry(void*, void*, uintptr_t); - probe CallStaticFloatMethodA__return(); - probe CallStaticFloatMethod__entry(void*, void*, uintptr_t); - probe CallStaticFloatMethod__return(); - probe CallStaticFloatMethodV__entry(void*, void*, uintptr_t); - probe CallStaticFloatMethodV__return(); - probe CallStaticIntMethodA__entry(void*, void*, uintptr_t); - probe CallStaticIntMethodA__return(uint32_t); - probe CallStaticIntMethod__entry(void*, void*, uintptr_t); - probe CallStaticIntMethod__return(uint32_t); - probe CallStaticIntMethodV__entry(void*, void*, uintptr_t); - probe CallStaticIntMethodV__return(uint32_t); - probe CallStaticLongMethodA__entry(void*, void*, uintptr_t); - probe CallStaticLongMethodA__return(uintptr_t); - probe CallStaticLongMethod__entry(void*, void*, uintptr_t); - probe CallStaticLongMethod__return(uintptr_t); - probe CallStaticLongMethodV__entry(void*, void*, uintptr_t); - probe CallStaticLongMethodV__return(uintptr_t); - probe CallStaticObjectMethodA__entry(void*, void*, uintptr_t); - probe CallStaticObjectMethodA__return(void*); - probe CallStaticObjectMethod__entry(void*, void*, uintptr_t); - probe CallStaticObjectMethod__return(void*); - probe CallStaticObjectMethodV__entry(void*, void*, uintptr_t); - probe CallStaticObjectMethodV__return(void*); - probe CallStaticShortMethodA__entry(void*, void*, uintptr_t); - probe CallStaticShortMethodA__return(uint16_t); - probe CallStaticShortMethod__entry(void*, void*, uintptr_t); - probe CallStaticShortMethod__return(uint16_t); - probe CallStaticShortMethodV__entry(void*, void*, uintptr_t); - probe CallStaticShortMethodV__return(uint16_t); - probe CallStaticVoidMethodA__entry(void*, void*, uintptr_t); - probe CallStaticVoidMethodA__return(); - probe CallStaticVoidMethod__entry(void*, void*, uintptr_t); - probe CallStaticVoidMethod__return(); - probe CallStaticVoidMethodV__entry(void*, void*, uintptr_t); - probe CallStaticVoidMethodV__return(); - probe CallVoidMethodA__entry(void*, void*, uintptr_t); - probe CallVoidMethodA__return(); - probe CallVoidMethod__entry(void*, void*, uintptr_t); - probe CallVoidMethod__return(); - probe CallVoidMethodV__entry(void*, void*, uintptr_t); - probe CallVoidMethodV__return(); - probe CreateJavaVM__entry(void**, void**, void*); - probe CreateJavaVM__return(uint32_t); - probe DefineClass__entry(void*, const char*, void*, char*, uintptr_t); - probe DefineClass__return(void*); - probe DeleteGlobalRef__entry(void*, void*); - probe DeleteGlobalRef__return(); - probe DeleteLocalRef__entry(void*, void*); - probe DeleteLocalRef__return(); - probe DeleteWeakGlobalRef__entry(void*, void*); - probe DeleteWeakGlobalRef__return(); - probe DestroyJavaVM__entry(void*); - probe DestroyJavaVM__return(uint32_t); - probe DetachCurrentThread__entry(void*); - probe DetachCurrentThread__return(uint32_t); - probe EnsureLocalCapacity__entry(void*, uint32_t); - probe EnsureLocalCapacity__return(uint32_t); - probe ExceptionCheck__entry(void*); - probe ExceptionCheck__return(uintptr_t); - probe ExceptionClear__entry(void*); - probe ExceptionClear__return(); - probe ExceptionDescribe__entry(void*); - probe ExceptionDescribe__return(); - probe ExceptionOccurred__entry(void*); - probe ExceptionOccurred__return(void*); - probe FatalError__entry(void* env, const char*); - probe FindClass__entry(void*, const char*); - probe FindClass__return(void*); - probe FromReflectedField__entry(void*, void*); - probe FromReflectedField__return(uintptr_t); - probe FromReflectedMethod__entry(void*, void*); - probe FromReflectedMethod__return(uintptr_t); - probe GetArrayLength__entry(void*, void*); - probe GetArrayLength__return(uintptr_t); - probe GetBooleanArrayElements__entry(void*, void*, uintptr_t*); - probe GetBooleanArrayElements__return(uintptr_t*); - probe GetBooleanArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uintptr_t*); - probe GetBooleanArrayRegion__return(); - probe GetBooleanField__entry(void*, void*, uintptr_t); - probe GetBooleanField__return(uintptr_t); - probe GetByteArrayElements__entry(void*, void*, uintptr_t*); - probe GetByteArrayElements__return(char*); - probe GetByteArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, char*); - probe GetByteArrayRegion__return(); - probe GetByteField__entry(void*, void*, uintptr_t); - probe GetByteField__return(char); - probe GetCharArrayElements__entry(void*, void*, uintptr_t*); - probe GetCharArrayElements__return(uint16_t*); - probe GetCharArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); - probe GetCharArrayRegion__return(); - probe GetCharField__entry(void*, void*, uintptr_t); - probe GetCharField__return(uint16_t); - probe GetCreatedJavaVMs__entry(void**, uintptr_t, uintptr_t*); - probe GetCreatedJavaVMs__return(uintptr_t); - probe GetDefaultJavaVMInitArgs__entry(void*); - probe GetDefaultJavaVMInitArgs__return(uint32_t); - probe GetDirectBufferAddress__entry(void*, void*); - probe GetDirectBufferAddress__return(void*); - probe GetDirectBufferCapacity__entry(void*, void*); - probe GetDirectBufferCapacity__return(uintptr_t); - probe GetDoubleArrayElements__entry(void*, void*, uintptr_t*); - probe GetDoubleArrayElements__return(double*); - probe GetDoubleArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, double*); - probe GetDoubleArrayRegion__return(); - probe GetDoubleField__entry(void*, void*, uintptr_t); - probe GetDoubleField__return(); - probe GetEnv__entry(void*, void*, uint32_t); - probe GetEnv__return(uint32_t); - probe GetFieldID__entry(void*, void*, const char*, const char*); - probe GetFieldID__return(uintptr_t); - probe GetFloatArrayElements__entry(void*, void*, uintptr_t*); - probe GetFloatArrayElements__return(float*); - probe GetFloatArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, float*); - probe GetFloatArrayRegion__return(); - probe GetFloatField__entry(void*, void*, uintptr_t); - probe GetFloatField__return(); - probe GetIntArrayElements__entry(void*, void*, uintptr_t*); - probe GetIntArrayElements__return(uint32_t*); - probe GetIntArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint32_t*); - probe GetIntArrayRegion__return(); - probe GetIntField__entry(void*, void*, uintptr_t); - probe GetIntField__return(uint32_t); - probe GetJavaVM__entry(void*, void**); - probe GetJavaVM__return(uint32_t); - probe GetLongArrayElements__entry(void*, void*, uintptr_t*); - probe GetLongArrayElements__return(uintptr_t*); - probe GetLongArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uintptr_t*); - probe GetLongArrayRegion__return(); - probe GetLongField__entry(void*, void*, uintptr_t); - probe GetLongField__return(uintptr_t); - probe GetMethodID__entry(void*, void*, const char*, const char*); - probe GetMethodID__return(uintptr_t); - probe GetObjectArrayElement__entry(void*, void*, uintptr_t); - probe GetObjectArrayElement__return(void*); - probe GetObjectClass__entry(void*, void*); - probe GetObjectClass__return(void*); - probe GetObjectField__entry(void*, void*, uintptr_t); - probe GetObjectField__return(void*); - probe GetObjectRefType__entry(void*, void*); - probe GetObjectRefType__return(void*); - probe GetPrimitiveArrayCritical__entry(void*, void*, uintptr_t*); - probe GetPrimitiveArrayCritical__return(void*); - probe GetShortArrayElements__entry(void*, void*, uintptr_t*); - probe GetShortArrayElements__return(uint16_t*); - probe GetShortArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); - probe GetShortArrayRegion__return(); - probe GetShortField__entry(void*, void*, uintptr_t); - probe GetShortField__return(uint16_t); - probe GetStaticBooleanField__entry(void*, void*, uintptr_t); - probe GetStaticBooleanField__return(uintptr_t); - probe GetStaticByteField__entry(void*, void*, uintptr_t); - probe GetStaticByteField__return(char); - probe GetStaticCharField__entry(void*, void*, uintptr_t); - probe GetStaticCharField__return(uint16_t); - probe GetStaticDoubleField__entry(void*, void*, uintptr_t); - probe GetStaticDoubleField__return(); - probe GetStaticFieldID__entry(void*, void*, const char*, const char*); - probe GetStaticFieldID__return(uintptr_t); - probe GetStaticFloatField__entry(void*, void*, uintptr_t); - probe GetStaticFloatField__return(); - probe GetStaticIntField__entry(void*, void*, uintptr_t); - probe GetStaticIntField__return(uint32_t); - probe GetStaticLongField__entry(void*, void*, uintptr_t); - probe GetStaticLongField__return(uintptr_t); - probe GetStaticMethodID__entry(void*, void*, const char*, const char*); - probe GetStaticMethodID__return(uintptr_t); - probe GetStaticObjectField__entry(void*, void*, uintptr_t); - probe GetStaticObjectField__return(void*); - probe GetStaticShortField__entry(void*, void*, uintptr_t); - probe GetStaticShortField__return(uint16_t); - probe GetStringChars__entry(void*, void*, uintptr_t*); - probe GetStringChars__return(const uint16_t*); - probe GetStringCritical__entry(void*, void*, uintptr_t*); - probe GetStringCritical__return(const uint16_t*); - probe GetStringLength__entry(void*, void*); - probe GetStringLength__return(uintptr_t); - probe GetStringRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); - probe GetStringRegion__return(); - probe GetStringUTFChars__entry(void*, void*, uintptr_t*); - probe GetStringUTFChars__return(const char*); - probe GetStringUTFLength__entry(void*, void*); - probe GetStringUTFLength__return(uintptr_t); - probe GetStringUTFRegion__entry(void*, void*, uintptr_t, uintptr_t, char*); - probe GetStringUTFRegion__return(); - probe GetSuperclass__entry(void*, void*); - probe GetSuperclass__return(void*); - probe GetVersion__entry(void*); - probe GetVersion__return(uint32_t); - probe IsAssignableFrom__entry(void*, void*, void*); - probe IsAssignableFrom__return(uintptr_t); - probe IsInstanceOf__entry(void*, void*, void*); - probe IsInstanceOf__return(uintptr_t); - probe IsSameObject__entry(void*, void*, void*); - probe IsSameObject__return(uintptr_t); - probe MonitorEnter__entry(void*, void*); - probe MonitorEnter__return(uint32_t); - probe MonitorExit__entry(void*, void*); - probe MonitorExit__return(uint32_t); - probe NewBooleanArray__entry(void*, uintptr_t); - probe NewBooleanArray__return(void*); - probe NewByteArray__entry(void*, uintptr_t); - probe NewByteArray__return(void*); - probe NewCharArray__entry(void*, uintptr_t); - probe NewCharArray__return(void*); - probe NewDirectByteBuffer__entry(void*, void*, uintptr_t); - probe NewDirectByteBuffer__return(void*); - probe NewDoubleArray__entry(void*, uintptr_t); - probe NewDoubleArray__return(void*); - probe NewFloatArray__entry(void*, uintptr_t); - probe NewFloatArray__return(void*); - probe NewGlobalRef__entry(void*, void*); - probe NewGlobalRef__return(void*); - probe NewIntArray__entry(void*, uintptr_t); - probe NewIntArray__return(void*); - probe NewLocalRef__entry(void*, void*); - probe NewLocalRef__return(void*); - probe NewLongArray__entry(void*, uintptr_t); - probe NewLongArray__return(void*); - probe NewObjectA__entry(void*, void*, uintptr_t); - probe NewObjectA__return(void*); - probe NewObjectArray__entry(void*, uintptr_t, void*, void*); - probe NewObjectArray__return(void*); - probe NewObject__entry(void*, void*, uintptr_t); - probe NewObject__return(void*); - probe NewObjectV__entry(void*, void*, uintptr_t); - probe NewObjectV__return(void*); - probe NewShortArray__entry(void*, uintptr_t); - probe NewShortArray__return(void*); - probe NewString__entry(void*, const uint16_t*, uintptr_t); - probe NewString__return(void*); - probe NewStringUTF__entry(void*, const char*); - probe NewStringUTF__return(void*); - probe NewWeakGlobalRef__entry(void*, void*); - probe NewWeakGlobalRef__return(void*); - probe PopLocalFrame__entry(void*, void*); - probe PopLocalFrame__return(void*); - probe PushLocalFrame__entry(void*, uint32_t); - probe PushLocalFrame__return(uint32_t); - probe RegisterNatives__entry(void*, void*, const void*, uint32_t); - probe RegisterNatives__return(uint32_t); - probe ReleaseBooleanArrayElements__entry(void*, void*, uintptr_t*, uint32_t); - probe ReleaseBooleanArrayElements__return(); - probe ReleaseByteArrayElements__entry(void*, void*, char*, uint32_t); - probe ReleaseByteArrayElements__return(); - probe ReleaseCharArrayElements__entry(void*, void*, uint16_t*, uint32_t); - probe ReleaseCharArrayElements__return(); - probe ReleaseDoubleArrayElements__entry(void*, void*, double*, uint32_t); - probe ReleaseDoubleArrayElements__return(); - probe ReleaseFloatArrayElements__entry(void*, void*, float*, uint32_t); - probe ReleaseFloatArrayElements__return(); - probe ReleaseIntArrayElements__entry(void*, void*, uint32_t*, uint32_t); - probe ReleaseIntArrayElements__return(); - probe ReleaseLongArrayElements__entry(void*, void*, uintptr_t*, uint32_t); - probe ReleaseLongArrayElements__return(); - probe ReleasePrimitiveArrayCritical__entry(void*, void*, void*, uint32_t); - probe ReleasePrimitiveArrayCritical__return(); - probe ReleaseShortArrayElements__entry(void*, void*, uint16_t*, uint32_t); - probe ReleaseShortArrayElements__return(); - probe ReleaseStringChars__entry(void*, void*, const uint16_t*); - probe ReleaseStringChars__return(); - probe ReleaseStringCritical__entry(void*, void*, const uint16_t*); - probe ReleaseStringCritical__return(); - probe ReleaseStringUTFChars__entry(void*, void*, const char*); - probe ReleaseStringUTFChars__return(); - probe SetBooleanArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uintptr_t*); - probe SetBooleanArrayRegion__return(); - probe SetBooleanField__entry(void*, void*, uintptr_t, uintptr_t); - probe SetBooleanField__return(); - probe SetByteArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const char*); - probe SetByteArrayRegion__return(); - probe SetByteField__entry(void*, void*, uintptr_t, char); - probe SetByteField__return(); - probe SetCharArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint16_t*); - probe SetCharArrayRegion__return(); - probe SetCharField__entry(void*, void*, uintptr_t, uint16_t); - probe SetCharField__return(); - probe SetDoubleArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const double*); - probe SetDoubleArrayRegion__return(); - probe SetDoubleField__entry(void*, void*, uintptr_t); - probe SetDoubleField__return(); - probe SetFloatArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const float*); - probe SetFloatArrayRegion__return(); - probe SetFloatField__entry(void*, void*, uintptr_t); - probe SetFloatField__return(); - probe SetIntArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint32_t*); - probe SetIntArrayRegion__return(); - probe SetIntField__entry(void*, void*, uintptr_t, uint32_t); - probe SetIntField__return(); - probe SetLongArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uintptr_t*); - probe SetLongArrayRegion__return(); - probe SetLongField__entry(void*, void*, uintptr_t, uintptr_t); - probe SetLongField__return(); - probe SetObjectArrayElement__entry(void*, void*, uintptr_t, void*); - probe SetObjectArrayElement__return(); - probe SetObjectField__entry(void*, void*, uintptr_t, void*); - probe SetObjectField__return(); - probe SetShortArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint16_t*); - probe SetShortArrayRegion__return(); - probe SetShortField__entry(void*, void*, uintptr_t, uint16_t); - probe SetShortField__return(); - probe SetStaticBooleanField__entry(void*, void*, uintptr_t, uintptr_t); - probe SetStaticBooleanField__return(); - probe SetStaticByteField__entry(void*, void*, uintptr_t, char); - probe SetStaticByteField__return(); - probe SetStaticCharField__entry(void*, void*, uintptr_t, uint16_t); - probe SetStaticCharField__return(); - probe SetStaticDoubleField__entry(void*, void*, uintptr_t); - probe SetStaticDoubleField__return(); - probe SetStaticFloatField__entry(void*, void*, uintptr_t); - probe SetStaticFloatField__return(); - probe SetStaticIntField__entry(void*, void*, uintptr_t, uint32_t); - probe SetStaticIntField__return(); - probe SetStaticLongField__entry(void*, void*, uintptr_t, uintptr_t); - probe SetStaticLongField__return(); - probe SetStaticObjectField__entry(void*, void*, uintptr_t, void*); - probe SetStaticObjectField__return(); - probe SetStaticShortField__entry(void*, void*, uintptr_t, uint16_t); - probe SetStaticShortField__return(); - probe Throw__entry(void*, void*); - probe Throw__return(intptr_t); - probe ThrowNew__entry(void*, void*, const char*); - probe ThrowNew__return(intptr_t); - probe ToReflectedField__entry(void*, void*, uintptr_t, uintptr_t); - probe ToReflectedField__return(void*); - probe ToReflectedMethod__entry(void*, void*, uintptr_t, uintptr_t); - probe ToReflectedMethod__return(void*); - probe UnregisterNatives__entry(void*, void*); - probe UnregisterNatives__return(uint32_t); -}; - -#pragma D attributes Standard/Standard/Common provider hotspot_jni provider -#pragma D attributes Private/Private/Unknown provider hotspot_jni module -#pragma D attributes Private/Private/Unknown provider hotspot_jni function -#pragma D attributes Standard/Standard/Common provider hotspot_jni name -#pragma D attributes Evolving/Evolving/Common provider hotspot_jni args - diff --git a/hotspot/src/share/vm/utilities/dtrace.hpp b/hotspot/src/share/vm/utilities/dtrace.hpp index 73f5f7c3fba..92d99de204a 100644 --- a/hotspot/src/share/vm/utilities/dtrace.hpp +++ b/hotspot/src/share/vm/utilities/dtrace.hpp @@ -38,24 +38,20 @@ #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() \ do { volatile size_t dtrace_workaround_tail_call_bug = 1; } while (0) -#define USDT2 1 -#include "dtracefiles/hotspot.h" -#include "dtracefiles/hotspot_jni.h" -#include "dtracefiles/hs_private.h" #elif defined(LINUX) #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() -#define USDT1 1 #elif defined(__APPLE__) #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() -#define USDT2 1 #include -#include "dtracefiles/hotspot.h" -#include "dtracefiles/hotspot_jni.h" -#include "dtracefiles/hs_private.h" #else #error "dtrace enabled for unknown os" #endif /* defined(SOLARIS) */ +#define USDT2 1 +#include "dtracefiles/hotspot.h" +#include "dtracefiles/hotspot_jni.h" +#include "dtracefiles/hs_private.h" + #else /* defined(DTRACE_ENABLED) */ #define DTRACE_ONLY(x) From 731320a7fdb7669e6a7be7aa2e0686fdf044d668 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Mon, 3 Feb 2014 15:24:20 +0100 Subject: [PATCH 121/265] 8033126: Can't call default methods from JNI Reviewed-by: dholmes, acorn, kamg --- hotspot/src/share/vm/prims/jni.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index a4201f1e84b..5d3327d1c23 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -1320,9 +1320,13 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive // interface call KlassHandle h_holder(THREAD, holder); - int itbl_index = m->itable_index(); - Klass* k = h_recv->klass(); - selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); + if (call_type == JNI_VIRTUAL) { + int itbl_index = m->itable_index(); + Klass* k = h_recv->klass(); + selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); + } else { + selected_method = m; + } } } From 465cfd7c0164b8dd737295442269476172652c11 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 4 Feb 2014 19:41:46 -0800 Subject: [PATCH 122/265] 8032223: nsk/regression/b4663146 gets assert(SafepointSynchronize::is_at_safepoint() || JvmtiEnv::is_thread_fully_suspended(get_thread(), false, &debug_bits)) It is better to calculate frame count for suspended threads at a safepoint Reviewed-by: twisti, dsamersoff, sla, dholmes, dcubed --- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 11 +++++++---- hotspot/src/share/vm/prims/jvmtiEnvBase.hpp | 14 +++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 318fe4e0b7e..6a197a84996 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1360,8 +1360,10 @@ JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) { if (state == NULL) { return JVMTI_ERROR_THREAD_NOT_ALIVE; } - uint32_t debug_bits = 0; - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == JavaThread::current()) { err = get_frame_count(state, count_ptr); } else { // get java stack frame count at safepoint. @@ -1476,9 +1478,10 @@ JvmtiEnv::PopFrame(JavaThread* java_thread) { jvmtiError JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) { jvmtiError err = JVMTI_ERROR_NONE; - uint32_t debug_bits = 0; - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == JavaThread::current()) { err = get_frame_location(java_thread, depth, method_ptr, location_ptr); } else { // JVMTI get java stack frame location at safepoint. diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index 084e19b45e4..0682118c88a 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -533,7 +533,11 @@ public: VMOp_Type type() const { return VMOp_GetFrameCount; } jvmtiError result() { return _result; } void doit() { - _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + JavaThread* jt = _state->get_thread(); + if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) { + _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); + } } }; @@ -559,8 +563,12 @@ public: VMOp_Type type() const { return VMOp_GetFrameLocation; } jvmtiError result() { return _result; } void doit() { - _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, - _method_ptr, _location_ptr); + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + if (Threads::includes(_java_thread) && !_java_thread->is_exiting() && + _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, + _method_ptr, _location_ptr); + } } }; From 05e4dd3c74cbac9e08f242a498562971cdb06919 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Wed, 5 Feb 2014 11:05:13 +0100 Subject: [PATCH 123/265] 8033426: Scale initial NewSize using NewRatio if not set on command line Now using NewRatio to size initial NewSize if not specified on commandline. Reviewed-by: jmasa, jwilhelm --- .../src/share/vm/memory/collectorPolicy.cpp | 127 ++++++++++++++++-- .../src/share/vm/memory/collectorPolicy.hpp | 1 + hotspot/src/share/vm/prims/jni.cpp | 2 + 3 files changed, 121 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index 17a88c08a86..a2f7166eda7 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -446,18 +446,20 @@ void GenCollectorPolicy::initialize_size_info() { _max_gen0_size = max_new_size; } else { size_t desired_new_size = 0; - if (!FLAG_IS_DEFAULT(NewSize)) { - // If NewSize is set ergonomically (for example by cms), it - // would make sense to use it. If it is used, also use it - // to set the initial size. Although there is no reason - // the minimum size and the initial size have to be the same, - // the current implementation gets into trouble during the calculation - // of the tenured generation sizes if they are different. - // Note that this makes the initial size and the minimum size - // generally small compared to the NewRatio calculation. + if (FLAG_IS_CMDLINE(NewSize)) { + // If NewSize is set on the command line, we must use it as + // the initial size and it also makes sense to use it as the + // lower limit. _min_gen0_size = NewSize; desired_new_size = NewSize; max_new_size = MAX2(max_new_size, NewSize); + } else if (FLAG_IS_ERGO(NewSize)) { + // If NewSize is set ergonomically, we should use it as a lower + // limit, but use NewRatio to calculate the initial size. + _min_gen0_size = NewSize; + desired_new_size = + MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); + max_new_size = MAX2(max_new_size, NewSize); } else { // For the case where NewSize is the default, use NewRatio // to size the minimum and initial generation sizes. @@ -980,3 +982,110 @@ void MarkSweepPolicy::initialize_gc_policy_counters() { _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 3); } } + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT +// Testing that the NewSize flag is handled correct is hard because it +// depends on so many other configurable variables. This test only tries to +// verify that there are some basic rules for NewSize honored by the policies. +class TestGenCollectorPolicy { +public: + static void test() { + size_t flag_value; + + save_flags(); + + // Set some limits that makes the math simple. + FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); + FLAG_SET_ERGO(uintx, InitialHeapSize, 120 * M); + Arguments::set_min_heap_size(40 * M); + + // If NewSize is set on the command line, it should be used + // for both min and initial young size if less than min heap. + flag_value = 20 * M; + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_min(flag_value); + verify_initial(flag_value); + + // If NewSize is set on command line, but is larger than the min + // heap size, it should only be used for initial young size. + flag_value = 80 * M; + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_initial(flag_value); + + // If NewSize has been ergonomically set, the collector policy + // should use it for min but calculate the initial young size + // using NewRatio. + flag_value = 20 * M; + FLAG_SET_ERGO(uintx, NewSize, flag_value); + verify_min(flag_value); + verify_scaled_initial(InitialHeapSize); + + restore_flags(); + + } + + static void verify_min(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.min_gen0_size() <= expected, err_msg("%zu > %zu", msp.min_gen0_size(), expected)); + } + + static void verify_initial(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); + } + + static void verify_scaled_initial(size_t initial_heap_size) { + MarkSweepPolicy msp; + msp.initialize_all(); + + size_t expected = msp.scale_by_NewRatio_aligned(initial_heap_size); + assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); + assert(FLAG_IS_ERGO(NewSize) && NewSize == expected, + err_msg("NewSize should have been set ergonomically to %zu, but was %zu", expected, NewSize)); + } + +private: + static size_t original_InitialHeapSize; + static size_t original_MaxHeapSize; + static size_t original_MaxNewSize; + static size_t original_MinHeapDeltaBytes; + static size_t original_NewSize; + static size_t original_OldSize; + + static void save_flags() { + original_InitialHeapSize = InitialHeapSize; + original_MaxHeapSize = MaxHeapSize; + original_MaxNewSize = MaxNewSize; + original_MinHeapDeltaBytes = MinHeapDeltaBytes; + original_NewSize = NewSize; + original_OldSize = OldSize; + } + + static void restore_flags() { + InitialHeapSize = original_InitialHeapSize; + MaxHeapSize = original_MaxHeapSize; + MaxNewSize = original_MaxNewSize; + MinHeapDeltaBytes = original_MinHeapDeltaBytes; + NewSize = original_NewSize; + OldSize = original_OldSize; + } +}; + +size_t TestGenCollectorPolicy::original_InitialHeapSize = 0; +size_t TestGenCollectorPolicy::original_MaxHeapSize = 0; +size_t TestGenCollectorPolicy::original_MaxNewSize = 0; +size_t TestGenCollectorPolicy::original_MinHeapDeltaBytes = 0; +size_t TestGenCollectorPolicy::original_NewSize = 0; +size_t TestGenCollectorPolicy::original_OldSize = 0; + +void TestNewSize_test() { + TestGenCollectorPolicy::test(); +} + +#endif diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index 815f1555726..57869225d3d 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -220,6 +220,7 @@ class ClearedAllSoftRefs : public StackObj { }; class GenCollectorPolicy : public CollectorPolicy { +friend class TestGenCollectorPolicy; protected: size_t _min_gen0_size; size_t _initial_gen0_size; diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 38d62977a34..1164448d3da 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -4954,6 +4954,7 @@ void TestMetaspaceAux_test(); void TestMetachunk_test(); void TestVirtualSpaceNode_test(); void TestOldFreeSpaceCalculation_test(); +void TestNewSize_test(); #if INCLUDE_ALL_GCS void TestG1BiasedArray_test(); void TestBufferingOopClosure_test(); @@ -4976,6 +4977,7 @@ void execute_internal_vm_tests() { run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); run_unit_test(TestOldFreeSpaceCalculation_test()); + run_unit_test(TestNewSize_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif From a3c78aac2f93ed928178bfd1711ed02c0179ce09 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 5 Feb 2014 15:14:47 -0800 Subject: [PATCH 124/265] 8032010: Attempt to resolve abstract method in concrete class fails with AbstractMethodError Removing a check in LinkResolver::resolve_method() to conform with a change in JVMS-8 5.4.3.3. Method Resolution Reviewed-by: coleenp, lfoltan --- .../src/share/vm/interpreter/linkResolver.cpp | 11 +- .../TestConcreteClassWithAbstractMethod.java | 181 ++++++++++++++++++ 2 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 hotspot/test/runtime/lambda-features/TestConcreteClassWithAbstractMethod.java diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 52c88bd3a66..aa11784b718 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -564,16 +564,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res } } - // 5. check if method is concrete - if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature)); - } - - // 6. access checks, access checking may be turned off when calling from within the VM. + // 5. access checks, access checking may be turned off when calling from within the VM. if (check_access) { assert(current_klass.not_null() , "current_klass should not be null"); diff --git a/hotspot/test/runtime/lambda-features/TestConcreteClassWithAbstractMethod.java b/hotspot/test/runtime/lambda-features/TestConcreteClassWithAbstractMethod.java new file mode 100644 index 00000000000..0fd1a426679 --- /dev/null +++ b/hotspot/test/runtime/lambda-features/TestConcreteClassWithAbstractMethod.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8032010 + * @summary method lookup on an abstract method in a concrete class should be successful + * @run main TestConcreteClassWithAbstractMethod + */ + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; + +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +/* + * class T1 { public int m() {} } + * class T2 { public abstract int m(); } + * class T3 { public int m() {} } + * + * Call site: T3.test() { invokevirtual T2.m() } + * T3.m() should be invoked + */ +public class TestConcreteClassWithAbstractMethod { + static final String classT1 = "p1.T1"; + static final String classT2 = "p1.T2"; + static final String classT3 = "p1.T3"; + + static final String callerName = classT3; + + public static void main(String[] args) throws Exception { + ClassLoader cl = new ClassLoader() { + public Class loadClass(String name) throws ClassNotFoundException { + if (findLoadedClass(name) != null) { + return findLoadedClass(name); + } + + if (classT1.equals(name)) { + byte[] classFile = dumpT1(); + return defineClass(classT1, classFile, 0, classFile.length); + } + if (classT2.equals(name)) { + byte[] classFile = dumpT2(); + return defineClass(classT2, classFile, 0, classFile.length); + } + if (classT3.equals(name)) { + byte[] classFile = dumpT3(); + return defineClass(classT3, classFile, 0, classFile.length); + } + + return super.loadClass(name); + } + }; + + cl.loadClass(classT1); + cl.loadClass(classT2); + cl.loadClass(classT3); + + //cl.loadClass(callerName).getDeclaredMethod("m"); + cl.loadClass(callerName).newInstance(); + + int result = (Integer)cl.loadClass(callerName).getDeclaredMethod("test").invoke(null); + System.out.println(""+result); + } + + public static byte[] dumpT1() { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_PUBLIC | ACC_SUPER, "p1/T1", null, "java/lang/Object", null); + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "m", "()I", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("p1/T1.m()"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); + mv.visitIntInsn(BIPUSH, 3); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + public static byte[] dumpT2() { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_PUBLIC | ACC_SUPER, "p1/T2", null, "p1/T1", null); + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "p1/T1", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + public static byte[] dumpT3() { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_PUBLIC + ACC_SUPER, "p1/T3", null, "p1/T2", null); + + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "p1/T2", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "m", "()I", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("p1/T3.m()"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); + mv.visitIntInsn(BIPUSH, 2); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "()I", null, null); + mv.visitCode(); + mv.visitTypeInsn(NEW, "p1/T3"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "p1/T3", "", "()V", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "p1/T2", "m", "()I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(3, 2); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} From aae536aad7c59b421c2a97c2830a23a2acca1b56 Mon Sep 17 00:00:00 2001 From: Henry Jen Date: Wed, 5 Feb 2014 21:24:29 -0800 Subject: [PATCH 125/265] 8033289: clang: clean up unused function warning Reviewed-by: coleenp, dholmes, mgerdin --- hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp | 4 ---- hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 2 ++ hotspot/src/share/vm/runtime/mutex.cpp | 10 ---------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index 544019c7179..462c0c58f89 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -107,10 +107,6 @@ static inline Address at_tos_p2() { return Address(rsp, Interpreter::expr_offset_in_bytes(2)); } -static inline Address at_tos_p3() { - return Address(rsp, Interpreter::expr_offset_in_bytes(3)); -} - // Condition conversion static Assembler::Condition j_not(TemplateTable::Condition cc) { switch (cc) { diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 977614648d3..8f2e1af6e44 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -2790,6 +2790,7 @@ inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) { return true; } +#ifdef ASSERT // verify that a static oop field is in range static inline bool verify_static_oop(InstanceKlass* ik, oop mirror, int offset) { @@ -2804,6 +2805,7 @@ static inline bool verify_static_oop(InstanceKlass* ik, return false; } } +#endif // #ifdef ASSERT // a class references its super class, interfaces, class loader, ... // and finally its static fields diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp index 4cd55e7d6f9..41e10bac28a 100644 --- a/hotspot/src/share/vm/runtime/mutex.cpp +++ b/hotspot/src/share/vm/runtime/mutex.cpp @@ -280,16 +280,6 @@ static inline jint MarsagliaXORV (jint x) { return x & 0x7FFFFFFF ; } -static inline jint MarsagliaXOR (jint * const a) { - jint x = *a ; - if (x == 0) x = UNS(a)|1 ; - x ^= x << 6; - x ^= ((unsigned)x) >> 21; - x ^= x << 7 ; - *a = x ; - return x & 0x7FFFFFFF ; -} - static int Stall (int its) { static volatile jint rv = 1 ; volatile int OnFrame = 0 ; From 41edfa7107bf30adbafa1c089822a0763122f7c9 Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Thu, 6 Feb 2014 17:59:35 +0000 Subject: [PATCH 126/265] 8030808: dtrace/hotspot/Monitors/Monitors001 fails in product builds on solaris-sparc Reviewed-by: sspitsyn, dcubed, kamg, dholmes --- hotspot/src/share/vm/runtime/synchronizer.cpp | 13 +++++++------ hotspot/src/share/vm/runtime/synchronizer.hpp | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 75e81704122..39a44775edc 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -373,23 +373,24 @@ ObjectLocker::~ObjectLocker() { // ----------------------------------------------------------------------------- // Wait/Notify/NotifyAll // NOTE: must use heavy weight monitor to handle wait() -void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { +int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { TEVENT (wait - throw IAX) ; - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj()); DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis); monitor->wait(millis, true, THREAD); - /* This dummy call is in place to get around dtrace bug 6254741. Once - that's fixed we can uncomment the following line and remove the call */ + // This dummy call is in place to get around dtrace bug 6254741. Once + // that's fixed we can uncomment the following line, remove the call + // and change this function back into a "void" func. // DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD); - dtrace_waited_probe(monitor, obj, THREAD); + return dtrace_waited_probe(monitor, obj, THREAD); } void ObjectSynchronizer::waitUninterruptibly (Handle obj, jlong millis, TRAPS) { diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index 4908c559c78..4f95b31350d 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ class ObjectSynchronizer : AllStatic { static void jni_exit (oop obj, Thread* THREAD); // Handle all interpreter, compiler and jni cases - static void wait (Handle obj, jlong millis, TRAPS); + static int wait (Handle obj, jlong millis, TRAPS); static void notify (Handle obj, TRAPS); static void notifyall (Handle obj, TRAPS); From 3eb1ac89c6bf92eb7cfda8746977256318b9b5db Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 6 Feb 2014 18:57:46 +0000 Subject: [PATCH 127/265] 8028735: runtime/RedefineObject/TestRedefineObject.java interrupted (timed out?) on solaris_sparcv9-fastdebug-c2-runtime and solaris_x64-debugOpen-c2-runtime Change GC loop counter to 100 which is enough to test the original problem but doesn't timeout the test. Reviewed-by: ctornqvi, lfoltan, mseledtsov, sla --- hotspot/test/runtime/RedefineObject/Agent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/test/runtime/RedefineObject/Agent.java b/hotspot/test/runtime/RedefineObject/Agent.java index d9c3656d8b2..b1c025da3cf 100644 --- a/hotspot/test/runtime/RedefineObject/Agent.java +++ b/hotspot/test/runtime/RedefineObject/Agent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,8 +65,8 @@ public class Agent implements ClassFileTransformer { public static void main(String[] args) { byte[] ba = new byte[0]; - // If it survives 1000 GC's, it's good. - for (int i = 0; i < 1000 ; i++) { + // If it survives 100 GC's, it's good. + for (int i = 0; i < 100 ; i++) { System.gc(); ba.clone(); } From d3a85e73a73ac2591e593ec2025fc2677efbb710 Mon Sep 17 00:00:00 2001 From: Gerald Thornbrugh Date: Thu, 6 Feb 2014 14:28:35 -0500 Subject: [PATCH 128/265] 8029775: Solaris code cleanup 8033464: Linux code cleanup Cleaned up warnings in solaris and linux specific os code. Reviewed-by: coleenp, fparain, dcubed --- hotspot/src/os/linux/vm/os_linux.cpp | 6 +++-- hotspot/src/os/linux/vm/perfMemory_linux.cpp | 14 ++++++++--- hotspot/src/os/solaris/vm/os_solaris.cpp | 25 +++++++++++++------ .../src/os/solaris/vm/perfMemory_solaris.cpp | 20 +++++++++++---- .../os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 11 +++++--- 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 1e3fc78b505..bf701718c35 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3000,7 +3000,9 @@ address get_stack_commited_bottom(address bottom, size_t size) { unsigned char vec[1]; unsigned imin = 1, imax = pages + 1, imid; - int mincore_return_value; + int mincore_return_value = 0; + + assert(imin < imax, "Unexpected page size"); while (imin < imax) { imid = (imax + imin) / 2; diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp index 87fc56b2b58..d95d33107e6 100644 --- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -891,8 +891,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor FREE_C_HEAP_ARRAY(char, filename, mtInternal); // open the shared memory file for the give vmid - fd = open_sharedmem_file(rfilename, file_flags, CHECK); - assert(fd != OS_ERR, "unexpected value"); + fd = open_sharedmem_file(rfilename, file_flags, THREAD); + + if (fd == OS_ERR) { + return; + } + + if (HAS_PENDING_EXCEPTION) { + ::close(fd); + return; + } if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 396e9df542e..19ab10b4444 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2232,8 +2232,8 @@ static bool check_addr0(outputStream* st) { st->cr(); status = true; } - ::close(fd); } + ::close(fd); } return status; } @@ -2257,13 +2257,18 @@ const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", "ILL_COPROC", "ILL_BADSTK" }; +const size_t ill_names_length = (sizeof(ill_names)/sizeof(char *)); + const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", "FPE_FLTINV", "FPE_FLTSUB" }; +const size_t fpe_names_length = (sizeof(fpe_names)/sizeof(char *)); const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; +const size_t segv_names_length = (sizeof(segv_names)/sizeof(char *)); const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; +const size_t bus_names_length = (sizeof(bus_names)/sizeof(char *)); void os::print_siginfo(outputStream* st, void* siginfo) { st->print("siginfo:"); @@ -2282,19 +2287,23 @@ void os::print_siginfo(outputStream* st, void* siginfo) { assert(c > 0, "unexpected si_code"); switch (si->si_signo) { case SIGILL: - st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); + st->print(", si_code=%d (%s)", c, + c >= ill_names_length ? "" : ill_names[c]); st->print(", si_addr=" PTR_FORMAT, si->si_addr); break; case SIGFPE: - st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); + st->print(", si_code=%d (%s)", c, + c >= fpe_names_length ? "" : fpe_names[c]); st->print(", si_addr=" PTR_FORMAT, si->si_addr); break; case SIGSEGV: - st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); + st->print(", si_code=%d (%s)", c, + c >= segv_names_length ? "" : segv_names[c]); st->print(", si_addr=" PTR_FORMAT, si->si_addr); break; case SIGBUS: - st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); + st->print(", si_code=%d (%s)", c, + c >= bus_names_length ? "" : bus_names[c]); st->print(", si_addr=" PTR_FORMAT, si->si_addr); break; default: @@ -3012,7 +3021,7 @@ bool os::get_page_info(char *start, page_info* info) { char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE }; const size_t types = sizeof(info_types) / sizeof(info_types[0]); - uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT]; + uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT + 1]; uint_t validity[MAX_MEMINFO_CNT]; size_t page_size = MAX2((size_t)os::vm_page_size(), page_expected->size); @@ -3051,7 +3060,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info } } - if (i != addrs_count) { + if (i < addrs_count) { if ((validity[i] & 2) != 0) { page_found->lgrp_id = outdata[types * i]; } else { diff --git a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp index e7b31ac6483..1fa30012d6b 100644 --- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp +++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -431,10 +431,12 @@ static char* get_user_name(int vmid, TRAPS) { RESTARTABLE(::read(fd, addr, remaining), result); if (result == OS_ERR) { + ::close(fd); THROW_MSG_0(vmSymbols::java_io_IOException(), "Read error"); + } else { + remaining-=result; + addr+=result; } - remaining-=result; - addr+=result; } ::close(fd); @@ -906,8 +908,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor FREE_C_HEAP_ARRAY(char, filename, mtInternal); // open the shared memory file for the give vmid - fd = open_sharedmem_file(rfilename, file_flags, CHECK); - assert(fd != OS_ERR, "unexpected value"); + fd = open_sharedmem_file(rfilename, file_flags, THREAD); + + if (fd == OS_ERR) { + return; + } + + if (HAS_PENDING_EXCEPTION) { + ::close(fd); + return; + } if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index eb8cbe81918..054a8132b3b 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -475,9 +475,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, // here if the underlying file has been truncated. // Do not crash the VM in such a case. CodeBlob* cb = CodeCache::find_blob_unsafe(pc); - nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; - if (nm != NULL && nm->has_unsafe_access()) { - stub = StubRoutines::handler_for_unsafe_access(); + if (cb != NULL) { + nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; + if (nm != NULL && nm->has_unsafe_access()) { + stub = StubRoutines::handler_for_unsafe_access(); + } } } else @@ -724,6 +726,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, err.report_and_die(); ShouldNotReachHere(); + return false; } void os::print_context(outputStream *st, void *context) { From 50b13833fa1608e2641102f7950959ed1cb10171 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Thu, 6 Feb 2014 20:13:38 -0800 Subject: [PATCH 129/265] 8025841: JVMTI: "vtable stub" dynamic code notification is misplaced Generate correct "vtable stub" dynamic code notifications Reviewed-by: sspitsyn, kvn, coleenp --- hotspot/src/share/vm/code/vtableStubs.cpp | 24 ++++++++++++++----- hotspot/src/share/vm/code/vtableStubs.hpp | 1 + .../share/vm/prims/jvmtiCodeBlobEvents.cpp | 17 +++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/code/vtableStubs.cpp b/hotspot/src/share/vm/code/vtableStubs.cpp index 5af91a3a6ee..b3bfc258f56 100644 --- a/hotspot/src/share/vm/code/vtableStubs.cpp +++ b/hotspot/src/share/vm/code/vtableStubs.cpp @@ -55,6 +55,9 @@ void* VtableStub::operator new(size_t size, int code_size) throw() { const int chunk_factor = 32; if (_chunk == NULL || _chunk + real_size > _chunk_end) { const int bytes = chunk_factor * real_size + pd_code_alignment(); + + // There is a dependency on the name of the blob in src/share/vm/prims/jvmtiCodeBlobEvents.cpp + // If changing the name, update the other file accordingly. BufferBlob* blob = BufferBlob::create("vtable chunks", bytes); if (blob == NULL) { return NULL; @@ -62,12 +65,6 @@ void* VtableStub::operator new(size_t size, int code_size) throw() { _chunk = blob->content_begin(); _chunk_end = _chunk + bytes; Forte::register_stub("vtable stub", _chunk, _chunk_end); - // Notify JVMTI about this stub. The event will be recorded by the enclosing - // JvmtiDynamicCodeEventCollector and posted when this thread has released - // all locks. - if (JvmtiExport::should_post_dynamic_code_generated()) { - JvmtiExport::post_dynamic_code_generated_while_holding_locks("vtable stub", _chunk, _chunk_end); - } align_chunk(); } assert(_chunk + real_size <= _chunk_end, "bad allocation"); @@ -130,6 +127,13 @@ address VtableStubs::find_stub(bool is_vtable_stub, int vtable_index) { is_vtable_stub? "vtbl": "itbl", vtable_index, VtableStub::receiver_location()); Disassembler::decode(s->code_begin(), s->code_end()); } + // Notify JVMTI about this stub. The event will be recorded by the enclosing + // JvmtiDynamicCodeEventCollector and posted when this thread has released + // all locks. + if (JvmtiExport::should_post_dynamic_code_generated()) { + JvmtiExport::post_dynamic_code_generated_while_holding_locks(is_vtable_stub? "vtable stub": "itable stub", + s->code_begin(), s->code_end()); + } } return s->entry_point(); } @@ -195,6 +199,14 @@ void vtableStubs_init() { VtableStubs::initialize(); } +void VtableStubs::vtable_stub_do(void f(VtableStub*)) { + for (int i = 0; i < N; i++) { + for (VtableStub* s = _table[i]; s != NULL; s = s->next()) { + f(s); + } + } +} + //----------------------------------------------------------------------------------------------------- // Non-product code diff --git a/hotspot/src/share/vm/code/vtableStubs.hpp b/hotspot/src/share/vm/code/vtableStubs.hpp index 06f2a67a857..b3d4f2d838e 100644 --- a/hotspot/src/share/vm/code/vtableStubs.hpp +++ b/hotspot/src/share/vm/code/vtableStubs.hpp @@ -131,6 +131,7 @@ class VtableStubs : AllStatic { static VtableStub* stub_containing(address pc); // stub containing pc or NULL static int number_of_vtable_stubs() { return _number_of_vtable_stubs; } static void initialize(); + static void vtable_stub_do(void f(VtableStub*)); // iterates over all vtable stubs }; #endif // SHARE_VM_CODE_VTABLESTUBS_HPP diff --git a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp index c46afdc1074..18d8786b81f 100644 --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp @@ -26,6 +26,7 @@ #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/scopeDesc.hpp" +#include "code/vtableStubs.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiCodeBlobEvents.hpp" @@ -63,6 +64,7 @@ class CodeBlobCollector : StackObj { // used during a collection static GrowableArray* _global_code_blobs; static void do_blob(CodeBlob* cb); + static void do_vtable_stub(VtableStub* vs); public: CodeBlobCollector() { _code_blobs = NULL; @@ -119,6 +121,10 @@ void CodeBlobCollector::do_blob(CodeBlob* cb) { if (cb->is_nmethod()) { return; } + // exclude VtableStubs, which are processed separately + if (cb->is_buffer_blob() && strcmp(cb->name(), "vtable chunks") == 0) { + return; + } // check if this starting address has been seen already - the // assumption is that stubs are inserted into the list before the @@ -136,6 +142,13 @@ void CodeBlobCollector::do_blob(CodeBlob* cb) { _global_code_blobs->append(scb); } +// called for each VtableStub in VtableStubs + +void CodeBlobCollector::do_vtable_stub(VtableStub* vs) { + JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(vs->is_vtable_stub() ? "vtable stub" : "itable stub", + vs->code_begin(), vs->code_end()); + _global_code_blobs->append(scb); +} // collects a list of CodeBlobs in the CodeCache. // @@ -166,6 +179,10 @@ void CodeBlobCollector::collect() { _global_code_blobs->append(new JvmtiCodeBlobDesc(desc->name(), desc->begin(), desc->end())); } + // Vtable stubs are not described with StubCodeDesc, + // process them separately + VtableStubs::vtable_stub_do(do_vtable_stub); + // next iterate over all the non-nmethod code blobs and add them to // the list - as noted above this will filter out duplicates and // enclosing blobs. From 62755b73589336a2ab352b696c5a9cc200409656 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 7 Feb 2014 09:03:44 -0800 Subject: [PATCH 130/265] 8033714: hotspot 'install_jvm' bld target broken with ZIP_DEBUGINFO_FILES=0 Fixed faulty logic in makefiles when compressed FDS builds are disabled Reviewed-by: rdurbin, dholmes, never, dnsimon, tbell --- hotspot/make/bsd/makefiles/jsig.make | 8 ++++---- hotspot/make/bsd/makefiles/saproc.make | 8 ++++---- hotspot/make/bsd/makefiles/vm.make | 8 ++++---- hotspot/make/linux/makefiles/jsig.make | 6 +++--- hotspot/make/linux/makefiles/saproc.make | 14 +++++++------- hotspot/make/linux/makefiles/vm.make | 6 +++--- hotspot/make/solaris/makefiles/jsig.make | 6 +++--- hotspot/make/solaris/makefiles/saproc.make | 14 +++++++------- hotspot/make/solaris/makefiles/vm.make | 6 +++--- 9 files changed, 38 insertions(+), 38 deletions(-) diff --git a/hotspot/make/bsd/makefiles/jsig.make b/hotspot/make/bsd/makefiles/jsig.make index b4802fb5069..220a5d091f6 100644 --- a/hotspot/make/bsd/makefiles/jsig.make +++ b/hotspot/make/bsd/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -91,13 +91,13 @@ endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" ifeq ($(OS_VENDOR), Darwin) - $(QUIETLY) test -d $(LIBJSIG_DEBUGINFO) && \ + $(QUIETLY) test ! -d $(LIBJSIG_DEBUGINFO) || \ cp -f -r $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) else - $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DEBUGINFO) || \ cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) endif - $(QUIETLY) test -f $(LIBJSIG_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \ cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" diff --git a/hotspot/make/bsd/makefiles/saproc.make b/hotspot/make/bsd/makefiles/saproc.make index 8cb38dbca47..a147325979f 100644 --- a/hotspot/make/bsd/makefiles/saproc.make +++ b/hotspot/make/bsd/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -153,13 +153,13 @@ endif install_saproc: $(BUILDLIBSAPROC) @echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)" ifeq ($(OS_VENDOR), Darwin) - $(QUIETLY) test -d $(LIBSAPROC_DEBUGINFO) && \ + $(QUIETLY) test ! -d $(LIBSAPROC_DEBUGINFO) || \ cp -f -r $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO) else - $(QUIETLY) test -f $(LIBSAPROC_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBSAPROC_DEBUGINFO) || \ cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO) endif - $(QUIETLY) test -f $(LIBSAPROC_DIZ) && \ + $(QUIETLY) test ! -f $(LIBSAPROC_DIZ) || \ cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ) $(QUIETLY) cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done" diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make index 3e8ea764066..3726ab6be77 100644 --- a/hotspot/make/bsd/makefiles/vm.make +++ b/hotspot/make/bsd/makefiles/vm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -367,13 +367,13 @@ DEST_JVM_DIZ = $(DEST_SUBDIR)/$(LIBJVM_DIZ) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" ifeq ($(OS_VENDOR), Darwin) - $(QUIETLY) test -d $(LIBJVM_DEBUGINFO) && \ + $(QUIETLY) test ! -d $(LIBJVM_DEBUGINFO) || \ cp -f -r $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) else - $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJVM_DEBUGINFO) || \ cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) endif - $(QUIETLY) test -f $(LIBJVM_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJVM_DIZ) || \ cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" diff --git a/hotspot/make/linux/makefiles/jsig.make b/hotspot/make/linux/makefiles/jsig.make index 6e13959482a..8295cbbe6ec 100644 --- a/hotspot/make/linux/makefiles/jsig.make +++ b/hotspot/make/linux/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,9 +74,9 @@ endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" - $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DEBUGINFO) || \ cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) - $(QUIETLY) test -f $(LIBJSIG_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \ cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" diff --git a/hotspot/make/linux/makefiles/saproc.make b/hotspot/make/linux/makefiles/saproc.make index 7e8f7c430f9..c2397491d43 100644 --- a/hotspot/make/linux/makefiles/saproc.make +++ b/hotspot/make/linux/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -113,13 +113,13 @@ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) endif install_saproc: $(BUILDLIBSAPROC) - $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ - echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ - test -f $(LIBSAPROC_DEBUGINFO) && \ + $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ + echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test ! -f $(LIBSAPROC_DEBUGINFO) || \ cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ - test -f $(LIBSAPROC_DIZ) && \ - cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \ - cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ + test ! -f $(LIBSAPROC_DIZ) || \ + cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \ + cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi .PHONY: install_saproc diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index 7df141f8895..442c9afb1bf 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -366,9 +366,9 @@ DEST_JVM_DIZ = $(DEST_SUBDIR)/$(LIBJVM_DIZ) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" - $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJVM_DEBUGINFO) || \ cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) - $(QUIETLY) test -f $(LIBJVM_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJVM_DIZ) || \ cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" diff --git a/hotspot/make/solaris/makefiles/jsig.make b/hotspot/make/solaris/makefiles/jsig.make index 59ac98401fc..0087fe958d8 100644 --- a/hotspot/make/solaris/makefiles/jsig.make +++ b/hotspot/make/solaris/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -79,9 +79,9 @@ endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" - $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DEBUGINFO) || \ cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) - $(QUIETLY) test -f $(LIBJSIG_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJSIG_DIZ) || \ cp -f $(LIBJSIG_DIZ) $(DEST_JSIG_DIZ) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" diff --git a/hotspot/make/solaris/makefiles/saproc.make b/hotspot/make/solaris/makefiles/saproc.make index 822735a5112..9721b8c065d 100644 --- a/hotspot/make/solaris/makefiles/saproc.make +++ b/hotspot/make/solaris/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -147,13 +147,13 @@ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) endif install_saproc: $(BULDLIBSAPROC) - $(QUIETLY) if [ -f $(LIBSAPROC) ] ; then \ - echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ - test -f $(LIBSAPROC_DEBUGINFO) && \ + $(QUIETLY) if [ -f $(LIBSAPROC) ] ; then \ + echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test ! -f $(LIBSAPROC_DEBUGINFO) || \ cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ - test -f $(LIBSAPROC_DIZ) && \ - cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \ - cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ + test ! -f $(LIBSAPROC_DIZ) || \ + cp -f $(LIBSAPROC_DIZ) $(DEST_SAPROC_DIZ); \ + cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi .PHONY: install_saproc diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index b3939fbe144..6c27eaa1d06 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -333,9 +333,9 @@ DEST_JVM_DIZ = $(DEST_SUBDIR)/$(LIBJVM_DIZ) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" - $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + $(QUIETLY) test ! -f $(LIBJVM_DEBUGINFO) || \ cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) - $(QUIETLY) test -f $(LIBJVM_DIZ) && \ + $(QUIETLY) test ! -f $(LIBJVM_DIZ) || \ cp -f $(LIBJVM_DIZ) $(DEST_JVM_DIZ) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" From 3d76a6654eead70c00fdd0df51477251ec75cbd2 Mon Sep 17 00:00:00 2001 From: Gerald Thornbrugh Date: Fri, 7 Feb 2014 11:47:24 -0800 Subject: [PATCH 131/265] 8033931: Several nightly tests failing with assert(imin < imax) failed: Unexpected page size Loosen new assert() in get_stack_commited_bottom() Reviewed-by: dcubed, coleenp, dsamersoff, hseigel --- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index bf701718c35..42f9471ea91 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -3002,7 +3002,7 @@ address get_stack_commited_bottom(address bottom, size_t size) { unsigned imin = 1, imax = pages + 1, imid; int mincore_return_value = 0; - assert(imin < imax, "Unexpected page size"); + assert(imin <= imax, "Unexpected page size"); while (imin < imax) { imid = (imax + imin) / 2; From 2759eb10aed0552b9bbd52bb18aacccd60ec0131 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 7 Feb 2014 18:30:27 -0500 Subject: [PATCH 132/265] 8033528: assert(0 <= i && i < length()) failed: index out of bounds Restoring bytecodes for invokedynamic had wrong index calculation added testing stress option. Reviewed-by: twisti, hseigel --- hotspot/src/share/vm/interpreter/rewriter.cpp | 43 ++++++++++++------- hotspot/src/share/vm/interpreter/rewriter.hpp | 5 ++- hotspot/src/share/vm/oops/constantPool.cpp | 3 ++ hotspot/src/share/vm/runtime/globals.hpp | 5 ++- hotspot/src/share/vm/utilities/array.hpp | 4 +- .../InvokespecialInterface.java | 3 +- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index 208f8617d5d..2474ae758ba 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -250,8 +250,8 @@ void Rewriter::rewrite_invokedynamic(address bcp, int offset, bool reverse) { // We will reverse the bytecode rewriting _after_ adjusting them. // Adjust the cache index by offset to the invokedynamic entries in the // cpCache plus the delta if the invokedynamic bytecodes were adjusted. - cache_index = cp_cache_delta() + _first_iteration_cp_cache_limit; - int cp_index = invokedynamic_cp_cache_entry_pool_index(cache_index); + int adjustment = cp_cache_delta() + _first_iteration_cp_cache_limit; + int cp_index = invokedynamic_cp_cache_entry_pool_index(cache_index - adjustment); assert(_pool->tag_at(cp_index).is_invoke_dynamic(), "wrong index"); // zero out 4 bytes Bytes::put_Java_u4(p, 0); @@ -453,18 +453,7 @@ methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) { return method; } -void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { - ResourceMark rm(THREAD); - Rewriter rw(klass, klass->constants(), klass->methods(), CHECK); - // (That's all, folks.) -} - - -Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array* methods, TRAPS) - : _klass(klass), - _pool(cpool), - _methods(methods) -{ +void Rewriter::rewrite_bytecodes(TRAPS) { assert(_pool->cache() == NULL, "constant pool cache must not be set yet"); // determine index maps for Method* rewriting @@ -508,6 +497,29 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Arrayconstants(), klass->methods(), CHECK); + // (That's all, folks.) +} + + +Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array* methods, TRAPS) + : _klass(klass), + _pool(cpool), + _methods(methods) +{ + + // Rewrite bytecodes - exception here exits. + rewrite_bytecodes(CHECK); + + // Stress restoring bytecodes + if (StressRewriter) { + restore_bytecodes(); + rewrite_bytecodes(CHECK); + } // allocate constant pool cache, now that we've seen all the bytecodes make_constant_pool_cache(THREAD); @@ -523,6 +535,7 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Arraylength(); for (int i = len-1; i >= 0; i--) { methodHandle m(THREAD, _methods->at(i)); diff --git a/hotspot/src/share/vm/interpreter/rewriter.hpp b/hotspot/src/share/vm/interpreter/rewriter.hpp index 2c7990fa7e5..aa4b7cd5228 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.hpp +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,6 +199,9 @@ class Rewriter: public StackObj { void patch_invokedynamic_bytecodes(); + // Do all the work. + void rewrite_bytecodes(TRAPS); + // Revert bytecodes in case of an exception. void restore_bytecodes(); diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 223fbc16935..e008ccb8d4a 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -82,6 +82,9 @@ ConstantPool::ConstantPool(Array* tags) { void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) { MetadataFactory::free_metadata(loader_data, cache()); set_cache(NULL); + MetadataFactory::free_array(loader_data, reference_map()); + set_reference_map(NULL); + MetadataFactory::free_array(loader_data, operands()); set_operands(NULL); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index b5d8880e91e..037743828b7 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1260,6 +1260,9 @@ class CommandLineFlags { develop(bool, TraceJNICalls, false, \ "Trace JNI calls") \ \ + develop(bool, StressRewriter, false, \ + "Stress linktime bytecode rewriting") \ + \ notproduct(bool, TraceJVMCalls, false, \ "Trace JVM calls") \ \ diff --git a/hotspot/src/share/vm/utilities/array.hpp b/hotspot/src/share/vm/utilities/array.hpp index 9f8e45f3243..0fbcd94d2be 100644 --- a/hotspot/src/share/vm/utilities/array.hpp +++ b/hotspot/src/share/vm/utilities/array.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ class ResourceArray: public ResourceObj { void initialize(size_t esize, int length) { assert(length >= 0, "illegal length"); - assert(_data == NULL, "must be new object"); + assert(StressRewriter || _data == NULL, "must be new object"); _length = length; _data = resource_allocate_bytes(esize * length); DEBUG_ONLY(init_nesting();) diff --git a/hotspot/test/runtime/lambda-features/InvokespecialInterface.java b/hotspot/test/runtime/lambda-features/InvokespecialInterface.java index 25e7904c257..80c26186da2 100644 --- a/hotspot/test/runtime/lambda-features/InvokespecialInterface.java +++ b/hotspot/test/runtime/lambda-features/InvokespecialInterface.java @@ -26,8 +26,9 @@ * @test * @bug 8032024 * @bug 8025937 + * @bug 8033528 * @summary [JDK 8] Test invokespecial and invokeinterface with the same JVM_CONSTANT_InterfaceMethodref - * @run main InvokespecialInterface + * @run main/othervm -XX:+StressRewriter InvokespecialInterface */ import java.util.function.*; import java.util.*; From dd25d6fed0fa237700f9e11b4de4403316dc4199 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Mon, 10 Feb 2014 17:49:17 +0100 Subject: [PATCH 133/265] 8016644: Improve UnsupportedClassVersionError message Improved the UnsupportedClassVersionError message to hopefully be more user friendly Reviewed-by: coleenp, dholmes, twisti --- .../share/vm/classfile/classFileParser.cpp | 14 ++-- .../UnsupportedClassFileVersion.java | 69 +++++++++++++++++++ .../oracle/java/testlibrary/ProcessTools.java | 13 +++- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/runtime/ClassFile/UnsupportedClassFileVersion.java diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index f45bb750269..41e7a7a62eb 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -3746,18 +3746,24 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), - "Unsupported major.minor version %u.%u", + "Unsupported class file version %u.%u, " + "this version of the Java Runtime only recognizes class file versions up to %u.%u", major_version, - minor_version); + minor_version, + JAVA_MAX_SUPPORTED_VERSION, + JAVA_MAX_SUPPORTED_MINOR_VERSION); } else { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_UnsupportedClassVersionError(), - "%s : Unsupported major.minor version %u.%u", + "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), " + "this version of the Java Runtime only recognizes class file versions up to %u.%u", name->as_C_string(), major_version, - minor_version); + minor_version, + JAVA_MAX_SUPPORTED_VERSION, + JAVA_MAX_SUPPORTED_MINOR_VERSION); } return nullHandle; } diff --git a/hotspot/test/runtime/ClassFile/UnsupportedClassFileVersion.java b/hotspot/test/runtime/ClassFile/UnsupportedClassFileVersion.java new file mode 100644 index 00000000000..7978d285a84 --- /dev/null +++ b/hotspot/test/runtime/ClassFile/UnsupportedClassFileVersion.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /testlibrary + * @compile -XDignore.symbol.file UnsupportedClassFileVersion.java + * @run main UnsupportedClassFileVersion + */ + +import java.io.File; +import java.io.FileOutputStream; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import com.oracle.java.testlibrary.*; + +public class UnsupportedClassFileVersion implements Opcodes { + public static void main(String... args) throws Exception { + writeClassFile(); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-cp", ".", "ClassFile"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("ClassFile has been compiled by a more recent version of the " + + "Java Runtime (class file version 99.0), this version of " + + "the Java Runtime only recognizes class file versions up to " + + System.getProperty("java.class.version")); + + output.shouldHaveExitValue(1); + } + + public static void writeClassFile() throws Exception { + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(99, ACC_PUBLIC + ACC_SUPER, "ClassFile", null, "java/lang/Object", null); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + cw.visitEnd(); + + try (FileOutputStream fos = new FileOutputStream(new File("ClassFile.class"))) { + fos.write(cw.toByteArray()); + } + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java index 56277f046ec..4bc11f8bf5d 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -142,11 +142,23 @@ public final class ProcessTools { * with any platform specific arguments prepended */ public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + return createJavaProcessBuilder(false, command); + } + + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmOptions, String... command) throws Exception { String javapath = JDKToolFinder.getJDKTool("java"); ArrayList args = new ArrayList<>(); args.add(javapath); Collections.addAll(args, getPlatformSpecificVMArgs()); + + if (addTestVmOptions) { + String vmopts = System.getProperty("test.vm.opts"); + if (vmopts != null) { + Collections.addAll(args, vmopts.split("\\s")); + } + } + Collections.addAll(args, command); // Reporting @@ -157,5 +169,4 @@ public final class ProcessTools { return new ProcessBuilder(args.toArray(new String[args.size()])); } - } From 57d286084a692193cd6a04b3992efef040317334 Mon Sep 17 00:00:00 2001 From: Ron Durbin Date: Mon, 10 Feb 2014 12:38:34 -0800 Subject: [PATCH 134/265] 8005262: possible gamma launcher issues Cleaned out make targets and comments associated with the previously removed gamma launcher Reviewed-by: dcubed, stefank --- hotspot/make/bsd/makefiles/optimized.make | 2 +- hotspot/make/bsd/makefiles/product.make | 2 +- hotspot/make/bsd/makefiles/top.make | 2 +- hotspot/make/linux/makefiles/optimized.make | 2 +- hotspot/make/linux/makefiles/product.make | 2 +- hotspot/make/linux/makefiles/top.make | 2 +- hotspot/make/solaris/makefiles/optimized.make | 2 +- hotspot/make/solaris/makefiles/product.make | 2 +- hotspot/make/solaris/makefiles/top.make | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hotspot/make/bsd/makefiles/optimized.make b/hotspot/make/bsd/makefiles/optimized.make index c89c3461ea5..f098efdbd82 100644 --- a/hotspot/make/bsd/makefiles/optimized.make +++ b/hotspot/make/bsd/makefiles/optimized.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/bsd/makefiles/product.make b/hotspot/make/bsd/makefiles/product.make index c67528eec79..7d3c345d38c 100644 --- a/hotspot/make/bsd/makefiles/product.make +++ b/hotspot/make/bsd/makefiles/product.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/bsd/makefiles/top.make b/hotspot/make/bsd/makefiles/top.make index aebadebe35c..6094e83c841 100644 --- a/hotspot/make/bsd/makefiles/top.make +++ b/hotspot/make/bsd/makefiles/top.make @@ -128,7 +128,7 @@ the_vm: vm_build_preliminaries $(adjust-mflags) @$(UpdatePCH) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install gamma: the_vm +install : the_vm @$(MAKE) -f vm.make $@ # next rules support "make foo.[ois]" diff --git a/hotspot/make/linux/makefiles/optimized.make b/hotspot/make/linux/makefiles/optimized.make index 07470f0756a..41d5e5d792e 100644 --- a/hotspot/make/linux/makefiles/optimized.make +++ b/hotspot/make/linux/makefiles/optimized.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/linux/makefiles/product.make b/hotspot/make/linux/makefiles/product.make index be241f41c92..70e23c6cb5e 100644 --- a/hotspot/make/linux/makefiles/product.make +++ b/hotspot/make/linux/makefiles/product.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/linux/makefiles/top.make b/hotspot/make/linux/makefiles/top.make index 8c6c2ca0194..aca73c6eb6c 100644 --- a/hotspot/make/linux/makefiles/top.make +++ b/hotspot/make/linux/makefiles/top.make @@ -122,7 +122,7 @@ the_vm: vm_build_preliminaries $(adjust-mflags) @$(UpdatePCH) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install gamma: the_vm +install: the_vm @$(MAKE) -f vm.make $@ # next rules support "make foo.[ois]" diff --git a/hotspot/make/solaris/makefiles/optimized.make b/hotspot/make/solaris/makefiles/optimized.make index 08a8c347351..f353628aec8 100644 --- a/hotspot/make/solaris/makefiles/optimized.make +++ b/hotspot/make/solaris/makefiles/optimized.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make index 0e26cbc82e1..1f9224b17f0 100644 --- a/hotspot/make/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -22,7 +22,7 @@ # # -# Sets make macros for making optimized version of Gamma VM +# Sets make macros for making optimized version of HotSpot VM # (This is the "product", not the "release" version.) # Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make diff --git a/hotspot/make/solaris/makefiles/top.make b/hotspot/make/solaris/makefiles/top.make index 19060bdd501..c211151b09f 100644 --- a/hotspot/make/solaris/makefiles/top.make +++ b/hotspot/make/solaris/makefiles/top.make @@ -114,7 +114,7 @@ $(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags the_vm: vm_build_preliminaries $(adjust-mflags) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install gamma: the_vm +install: the_vm @$(MAKE) -f vm.make $@ # next rules support "make foo.[oi]" From cf5c3370a39083442e7ec98a84a19db450687daa Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Mon, 10 Feb 2014 12:48:54 -0800 Subject: [PATCH 135/265] 8028073: race condition in ObjectMonitor implementation causing deadlocks Move redo of ParkEvent.unpark() after JVMTI_EVENT_MONITOR_WAITED event handler is called. Reviewed-by: dholmes, sspitsyn, dice, acorn --- hotspot/src/share/vm/prims/jvm.cpp | 8 ++- .../src/share/vm/runtime/objectMonitor.cpp | 56 +++++++++++++------ 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 1059783eb05..74c0df13326 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -518,6 +518,12 @@ JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)) JavaThreadInObjectWaitState jtiows(thread, ms != 0); if (JvmtiExport::should_post_monitor_wait()) { JvmtiExport::post_monitor_wait((JavaThread *)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 + // made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT + // event handler cannot accidentally consume an unpark() meant for + // the ParkEvent associated with this ObjectMonitor. } ObjectSynchronizer::wait(obj, ms, CHECK); JVM_END diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 5ab77844195..9b86b43b636 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -382,6 +382,12 @@ void ATTR ObjectMonitor::enter(TRAPS) { DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_enter()) { JvmtiExport::post_monitor_contended_enter(jt, this); + + // The current thread does not yet own the monitor and does not + // yet appear on any queues that would get it made the successor. + // This means that the JVMTI_EVENT_MONITOR_CONTENDED_ENTER event + // handler cannot accidentally consume an unpark() meant for the + // ParkEvent associated with this ObjectMonitor. } OSThreadContendState osts(Self->osthread()); @@ -439,6 +445,12 @@ void ATTR ObjectMonitor::enter(TRAPS) { DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt); if (JvmtiExport::should_post_monitor_contended_entered()) { JvmtiExport::post_monitor_contended_entered(jt, this); + + // The current thread already owns the monitor and is not going to + // call park() for the remainder of the monitor enter protocol. So + // it doesn't matter if the JVMTI_EVENT_MONITOR_CONTENDED_ENTERED + // event handler consumed an unpark() issued by the thread that + // just exited the monitor. } if (event.should_commit()) { @@ -1456,6 +1468,14 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // Note: 'false' parameter is passed here because the // wait was not timed out due to thread interrupt. JvmtiExport::post_monitor_waited(jt, this, false); + + // In this short circuit of the monitor wait protocol, the + // current thread never drops ownership of the monitor and + // never gets added to the wait queue so the current thread + // cannot be made the successor. This means that the + // JVMTI_EVENT_MONITOR_WAITED event handler cannot accidentally + // consume an unpark() meant for the ParkEvent associated with + // this ObjectMonitor. } if (event.should_commit()) { post_monitor_wait_event(&event, 0, millis, false); @@ -1499,21 +1519,6 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { exit (true, Self) ; // exit the monitor guarantee (_owner != Self, "invariant") ; - // As soon as the ObjectMonitor's ownership is dropped in the exit() - // call above, another thread can enter() the ObjectMonitor, do the - // notify(), and exit() the ObjectMonitor. If the other thread's - // exit() call chooses this thread as the successor and the unpark() - // call happens to occur while this thread is posting a - // MONITOR_CONTENDED_EXIT event, then we run the risk of the event - // handler using RawMonitors and consuming the unpark(). - // - // To avoid the problem, we re-post the event. This does no harm - // even if the original unpark() was not consumed because we are the - // chosen successor for this monitor. - if (node._notified != 0 && _succ == Self) { - node._event->unpark(); - } - // The thread is on the WaitSet list - now park() it. // On MP systems it's conceivable that a brief spin before we park // could be profitable. @@ -1595,6 +1600,25 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // post monitor waited event. Note that this is past-tense, we are done waiting. if (JvmtiExport::should_post_monitor_waited()) { JvmtiExport::post_monitor_waited(jt, this, ret == OS_TIMEOUT); + + if (node._notified != 0 && _succ == Self) { + // In this part of the monitor wait-notify-reenter protocol it + // is possible (and normal) for another thread to do a fastpath + // monitor enter-exit while this thread is still trying to get + // to the reenter portion of the protocol. + // + // The ObjectMonitor was notified and the current thread is + // the successor which also means that an unpark() has already + // been done. The JVMTI_EVENT_MONITOR_WAITED event handler can + // consume the unpark() that was done when the successor was + // set because the same ParkEvent is shared between Java + // monitors and JVM/TI RawMonitors (for now). + // + // We redo the unpark() to ensure forward progress, i.e., we + // don't want all pending threads hanging (parked) with none + // entering the unlocked monitor. + node._event->unpark(); + } } if (event.should_commit()) { From a90e842e0c04a51c799ab8c9276c4198da727ec8 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Mon, 10 Feb 2014 21:29:14 -0800 Subject: [PATCH 136/265] 8033792: AltHashing used jint for imprecise bit shifting AltHashing used jint the way of juint in bit shifting which could lead loss of precision. Fix by change _seed defined as juint. Reviewed-by: coleenp, ccheung --- hotspot/src/share/vm/classfile/altHashing.cpp | 78 +++++++++---------- hotspot/src/share/vm/classfile/altHashing.hpp | 20 ++--- hotspot/src/share/vm/oops/instanceKlass.hpp | 3 +- hotspot/src/share/vm/oops/metadata.hpp | 4 +- hotspot/src/share/vm/oops/oop.cpp | 4 +- hotspot/src/share/vm/oops/oop.hpp | 4 +- hotspot/src/share/vm/oops/symbol.cpp | 4 +- hotspot/src/share/vm/oops/symbol.hpp | 4 +- hotspot/src/share/vm/utilities/hashtable.cpp | 4 +- hotspot/src/share/vm/utilities/hashtable.hpp | 6 +- 10 files changed, 66 insertions(+), 65 deletions(-) diff --git a/hotspot/src/share/vm/classfile/altHashing.cpp b/hotspot/src/share/vm/classfile/altHashing.cpp index 8dfc3153ca4..91eb5bec152 100644 --- a/hotspot/src/share/vm/classfile/altHashing.cpp +++ b/hotspot/src/share/vm/classfile/altHashing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,18 +39,18 @@ intptr_t object_hash(Klass* k) { } // Seed value used for each alternative hash calculated. -jint AltHashing::compute_seed() { +juint AltHashing::compute_seed() { jlong nanos = os::javaTimeNanos(); jlong now = os::javaTimeMillis(); - jint SEED_MATERIAL[8] = { - (jint) object_hash(SystemDictionary::String_klass()), - (jint) object_hash(SystemDictionary::System_klass()), - (jint) os::random(), // current thread isn't a java thread - (jint) (((julong)nanos) >> 32), - (jint) nanos, - (jint) (((julong)now) >> 32), - (jint) now, - (jint) (os::javaTimeNanos() >> 2) + int SEED_MATERIAL[8] = { + (int) object_hash(SystemDictionary::String_klass()), + (int) object_hash(SystemDictionary::System_klass()), + (int) os::random(), // current thread isn't a java thread + (int) (((julong)nanos) >> 32), + (int) nanos, + (int) (((julong)now) >> 32), + (int) now, + (int) (os::javaTimeNanos() >> 2) }; return murmur3_32(SEED_MATERIAL, 8); @@ -58,14 +58,14 @@ jint AltHashing::compute_seed() { // Murmur3 hashing for Symbol -jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) { - jint h1 = seed; +juint AltHashing::murmur3_32(juint seed, const jbyte* data, int len) { + juint h1 = seed; int count = len; int offset = 0; // body while (count >= 4) { - jint k1 = (data[offset] & 0x0FF) + juint k1 = (data[offset] & 0x0FF) | (data[offset + 1] & 0x0FF) << 8 | (data[offset + 2] & 0x0FF) << 16 | data[offset + 3] << 24; @@ -85,7 +85,7 @@ jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) { // tail if (count > 0) { - jint k1 = 0; + juint k1 = 0; switch (count) { case 3: @@ -109,18 +109,18 @@ jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) { h1 ^= len; // finalization mix force all bits of a hash block to avalanche - h1 ^= ((unsigned int)h1) >> 16; + h1 ^= h1 >> 16; h1 *= 0x85ebca6b; - h1 ^= ((unsigned int)h1) >> 13; + h1 ^= h1 >> 13; h1 *= 0xc2b2ae35; - h1 ^= ((unsigned int)h1) >> 16; + h1 ^= h1 >> 16; return h1; } // Murmur3 hashing for Strings -jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) { - jint h1 = seed; +juint AltHashing::murmur3_32(juint seed, const jchar* data, int len) { + juint h1 = seed; int off = 0; int count = len; @@ -129,7 +129,7 @@ jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) { while (count >= 2) { jchar d1 = data[off++] & 0xFFFF; jchar d2 = data[off++]; - jint k1 = (d1 | d2 << 16); + juint k1 = (d1 | d2 << 16); count -= 2; @@ -145,7 +145,7 @@ jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) { // tail if (count > 0) { - int k1 = data[off]; + juint k1 = (juint)data[off]; k1 *= 0xcc9e2d51; k1 = Integer_rotateLeft(k1, 15); @@ -157,25 +157,25 @@ jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) { h1 ^= len * 2; // (Character.SIZE / Byte.SIZE); // finalization mix force all bits of a hash block to avalanche - h1 ^= ((unsigned int)h1) >> 16; + h1 ^= h1 >> 16; h1 *= 0x85ebca6b; - h1 ^= ((unsigned int)h1) >> 13; + h1 ^= h1 >> 13; h1 *= 0xc2b2ae35; - h1 ^= ((unsigned int)h1) >> 16; + h1 ^= h1 >> 16; return h1; } // Hash used for the seed. -jint AltHashing::murmur3_32(jint seed, const int* data, int len) { - jint h1 = seed; +juint AltHashing::murmur3_32(juint seed, const int* data, int len) { + juint h1 = seed; int off = 0; int end = len; // body while (off < end) { - jint k1 = data[off++]; + juint k1 = (juint)data[off++]; k1 *= 0xcc9e2d51; k1 = Integer_rotateLeft(k1, 15); @@ -193,26 +193,26 @@ jint AltHashing::murmur3_32(jint seed, const int* data, int len) { h1 ^= len * 4; // (Integer.SIZE / Byte.SIZE); // finalization mix force all bits of a hash block to avalanche - h1 ^= ((juint)h1) >> 16; + h1 ^= h1 >> 16; h1 *= 0x85ebca6b; - h1 ^= ((juint)h1) >> 13; + h1 ^= h1 >> 13; h1 *= 0xc2b2ae35; - h1 ^= ((juint)h1) >> 16; + h1 ^= h1 >> 16; return h1; } -jint AltHashing::murmur3_32(const int* data, int len) { +juint AltHashing::murmur3_32(const int* data, int len) { return murmur3_32(0, data, len); } #ifndef PRODUCT // Overloaded versions for internal test. -jint AltHashing::murmur3_32(const jbyte* data, int len) { +juint AltHashing::murmur3_32(const jbyte* data, int len) { return murmur3_32(0, data, len); } -jint AltHashing::murmur3_32(const jchar* data, int len) { +juint AltHashing::murmur3_32(const jchar* data, int len) { return murmur3_32(0, data, len); } @@ -251,11 +251,11 @@ void AltHashing::testMurmur3_32_ByteArray() { // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255} for (int i = 0; i < 256; i++) { - jint hash = murmur3_32(256 - i, vector, i); + juint hash = murmur3_32(256 - i, vector, i); hashes[i * 4] = (jbyte) hash; - hashes[i * 4 + 1] = (jbyte) (((juint)hash) >> 8); - hashes[i * 4 + 2] = (jbyte) (((juint)hash) >> 16); - hashes[i * 4 + 3] = (jbyte) (((juint)hash) >> 24); + hashes[i * 4 + 1] = (jbyte)(hash >> 8); + hashes[i * 4 + 2] = (jbyte)(hash >> 16); + hashes[i * 4 + 3] = (jbyte)(hash >> 24); } // hash to get const result. @@ -269,7 +269,7 @@ void AltHashing::testMurmur3_32_ByteArray() { } void AltHashing::testEquivalentHashes() { - jint jbytes, jchars, ints; + juint jbytes, jchars, ints; // printf("testEquivalentHashes\n"); diff --git a/hotspot/src/share/vm/classfile/altHashing.hpp b/hotspot/src/share/vm/classfile/altHashing.hpp index 941b9a0dc37..2e04fd33a2d 100644 --- a/hotspot/src/share/vm/classfile/altHashing.hpp +++ b/hotspot/src/share/vm/classfile/altHashing.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,24 +39,24 @@ class AltHashing : AllStatic { // utility function copied from java/lang/Integer - static jint Integer_rotateLeft(jint i, int distance) { - return (i << distance) | (((juint)i) >> (32-distance)); + static juint Integer_rotateLeft(juint i, int distance) { + return (i << distance) | (i >> (32-distance)); } - static jint murmur3_32(const int* data, int len); - static jint murmur3_32(jint seed, const int* data, int len); + static juint murmur3_32(const int* data, int len); + static juint murmur3_32(juint seed, const int* data, int len); #ifndef PRODUCT // Hashing functions used for internal testing - static jint murmur3_32(const jbyte* data, int len); - static jint murmur3_32(const jchar* data, int len); + static juint murmur3_32(const jbyte* data, int len); + static juint murmur3_32(const jchar* data, int len); static void testMurmur3_32_ByteArray(); static void testEquivalentHashes(); #endif // PRODUCT public: - static jint compute_seed(); - static jint murmur3_32(jint seed, const jbyte* data, int len); - static jint murmur3_32(jint seed, const jchar* data, int len); + static juint compute_seed(); + static juint murmur3_32(juint seed, const jbyte* data, int len); + static juint murmur3_32(juint seed, const jchar* data, int len); NOT_PRODUCT(static void test_alt_hash();) }; #endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 2b7a73a3189..f503de6725a 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -554,6 +554,7 @@ class InstanceKlass: public Klass { if (hk == NULL) { return NULL; } else { + assert(*hk != NULL, "host klass should always be set if the address is not null"); return *hk; } } diff --git a/hotspot/src/share/vm/oops/metadata.hpp b/hotspot/src/share/vm/oops/metadata.hpp index a1afb0d0562..84a60893e81 100644 --- a/hotspot/src/share/vm/oops/metadata.hpp +++ b/hotspot/src/share/vm/oops/metadata.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ class Metadata : public MetaspaceObj { int identity_hash() { return (int)(uintptr_t)this; } // Rehashing support for tables containing pointers to this - unsigned int new_hash(jint seed) { ShouldNotReachHere(); return 0; } + unsigned int new_hash(juint seed) { ShouldNotReachHere(); return 0; } virtual bool is_klass() const volatile { return false; } virtual bool is_method() const volatile { return false; } diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index aed29da6796..281188354a0 100644 --- a/hotspot/src/share/vm/oops/oop.cpp +++ b/hotspot/src/share/vm/oops/oop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,7 @@ intptr_t oopDesc::slow_identity_hash() { } // When String table needs to rehash -unsigned int oopDesc::new_hash(jint seed) { +unsigned int oopDesc::new_hash(juint seed) { EXCEPTION_MARK; ResourceMark rm; int length; diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 350c0fc6131..2013c3ea758 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -362,7 +362,7 @@ class oopDesc { intptr_t slow_identity_hash(); // Alternate hashing code if string table is rehashed - unsigned int new_hash(jint seed); + unsigned int new_hash(juint seed); // marks are forwarded to stack when object is locked bool has_displaced_mark() const; diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index 2a2c975b6ef..cab865503fa 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,7 +207,7 @@ const char* Symbol::as_klass_external_name() const { } // Alternate hashing for unbalanced symbol tables. -unsigned int Symbol::new_hash(jint seed) { +unsigned int Symbol::new_hash(juint seed) { ResourceMark rm; // Use alternate hashing algorithm on this symbol. return AltHashing::murmur3_32(seed, (const jbyte*)as_C_string(), utf8_length()); diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index e747c464607..aaa55c58992 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,7 +154,7 @@ class Symbol : private SymbolBase { int identity_hash() { return _identity_hash; } // For symbol table alternate hashing - unsigned int new_hash(jint seed); + unsigned int new_hash(juint seed); // Reference counting. See comments above this class for when to use. int refcount() const { return _refcount; } diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp index 3e1413f618f..40fb3b1537d 100644 --- a/hotspot/src/share/vm/utilities/hashtable.cpp +++ b/hotspot/src/share/vm/utilities/hashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ template bool BasicHashtable::check_rehash_table(int count) { return false; } -template jint Hashtable::_seed = 0; +template juint Hashtable::_seed = 0; // Create a new table and using alternate hash code, populate the new table // with the existing elements. This can be used to change the hash code diff --git a/hotspot/src/share/vm/utilities/hashtable.hpp b/hotspot/src/share/vm/utilities/hashtable.hpp index 468965dab3b..aa45100249c 100644 --- a/hotspot/src/share/vm/utilities/hashtable.hpp +++ b/hotspot/src/share/vm/utilities/hashtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -280,7 +280,7 @@ protected: // Function to move these elements into the new table. void move_to(Hashtable* new_table); static bool use_alternate_hashcode() { return _seed != 0; } - static jint seed() { return _seed; } + static juint seed() { return _seed; } static int literal_size(Symbol *symbol); static int literal_size(oop oop); @@ -296,7 +296,7 @@ public: void dump_table(outputStream* st, const char *table_name); private: - static jint _seed; + static juint _seed; }; From 2a866afcdbc63751170fca81f8415e3c11a0f5d0 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 13 Feb 2014 17:44:39 +0100 Subject: [PATCH 137/265] 8034761: Remove the do_code_roots parameter from process_strong_roots Reviewed-by: tschatzl, mgerdin, jmasa --- .../concurrentMarkSweepGeneration.cpp | 12 ---------- .../concurrentMarkSweepGeneration.hpp | 7 ------ .../gc_implementation/g1/g1CollectedHeap.cpp | 22 +++++++------------ .../gc_implementation/g1/g1CollectedHeap.hpp | 5 ----- .../vm/gc_implementation/g1/g1MarkSweep.cpp | 6 ++--- .../parNew/parNewGeneration.cpp | 1 - .../vm/gc_implementation/shared/markSweep.cpp | 1 - .../vm/gc_implementation/shared/markSweep.hpp | 1 - .../src/share/vm/memory/defNewGeneration.cpp | 1 - .../src/share/vm/memory/genCollectedHeap.cpp | 17 ++++---------- .../src/share/vm/memory/genCollectedHeap.hpp | 10 ++++----- hotspot/src/share/vm/memory/genMarkSweep.cpp | 11 ++-------- hotspot/src/share/vm/memory/sharedHeap.cpp | 19 ++++++++-------- hotspot/src/share/vm/memory/sharedHeap.hpp | 13 ++++++----- 14 files changed, 36 insertions(+), 90 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 847a8326fa0..5807db38eed 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -3035,7 +3035,6 @@ void CMSCollector::verify_after_remark_work_1() { true, // activate StrongRootsScope SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, - true, // walk code active on stacks NULL, NULL); // SSS: Provide correct closure @@ -3102,7 +3101,6 @@ void CMSCollector::verify_after_remark_work_2() { true, // activate StrongRootsScope SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, - true, // walk code active on stacks NULL, &klass_closure); @@ -3680,12 +3678,6 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) { ResourceMark rm; HandleMark hm; - FalseClosure falseClosure; - // In the case of a synchronous collection, we will elide the - // remark step, so it's important to catch all the nmethod oops - // in this step. - // The final 'true' flag to gen_process_strong_roots will ensure this. - // If 'async' is true, we can relax the nmethod tracing. MarkRefsIntoClosure notOlder(_span, &_markBitMap); GenCollectedHeap* gch = GenCollectedHeap::heap(); @@ -3738,7 +3730,6 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) { true, // activate StrongRootsScope SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, - true, // walk all of code cache if (so & SO_AllCodeCache) NULL, &klass_closure); } @@ -5237,7 +5228,6 @@ void CMSParInitialMarkTask::work(uint worker_id) { false, // this is parallel code SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), &par_mri_cl, - true, // walk all of code cache if (so & SO_AllCodeCache) NULL, &klass_closure); assert(_collector->should_unload_classes() @@ -5373,7 +5363,6 @@ void CMSParRemarkTask::work(uint worker_id) { false, // this is parallel code SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), &par_mrias_cl, - true, // walk all of code cache if (so & SO_AllCodeCache) NULL, NULL); // The dirty klasses will be handled below assert(_collector->should_unload_classes() @@ -5963,7 +5952,6 @@ void CMSCollector::do_remark_non_parallel() { false, // use the local StrongRootsScope SharedHeap::ScanningOption(roots_scanning_options()), &mrias_cl, - true, // walk code active on stacks NULL, NULL); // The dirty klasses will be handled below diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index e98e8b6ce28..3c771ef3946 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -1383,13 +1383,6 @@ class ASConcurrentMarkSweepGeneration : public ConcurrentMarkSweepGeneration { // Closures of various sorts used by CMS to accomplish its work // -// This closure is used to check that a certain set of oops is empty. -class FalseClosure: public OopClosure { - public: - void do_oop(oop* p) { guarantee(false, "Should be an empty set"); } - void do_oop(narrowOop* p) { guarantee(false, "Should be an empty set"); } -}; - // This closure is used to do concurrent marking from the roots // following the first checkpoint. class MarkFromRootsClosure: public BitMapClosure { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index f027f29491c..c9e43171368 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3394,13 +3394,12 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { if (!silent) { gclog_or_tty->print("Roots "); } VerifyRootsClosure rootsCl(vo); - G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo); - G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl); VerifyKlassClosure klassCl(this, &rootsCl); // We apply the relevant closures to all the oops in the - // system dictionary, the string table and the code cache. - const int so = SO_AllClasses | SO_Strings | SO_AllCodeCache; + // system dictionary, class loader data graph and the string table. + // Don't verify the code cache here, since it's verified below. + const int so = SO_AllClasses | SO_Strings; // Need cleared claim bits for the strong roots processing ClassLoaderDataGraph::clear_claimed_marks(); @@ -3408,10 +3407,14 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { process_strong_roots(true, // activate StrongRootsScope ScanningOption(so), // roots scanning options &rootsCl, - &blobsCl, &klassCl ); + // Verify the nmethods in the code cache. + G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo); + G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl); + CodeCache::blobs_do(&blobsCl); + bool failures = rootsCl.failures() || codeRootsCl.failures(); if (vo != VerifyOption_G1UseMarkWord) { @@ -5115,12 +5118,9 @@ g1_process_strong_roots(bool is_scavenging, BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); - CodeBlobToOopClosure scan_code_roots(&buf_scan_non_heap_roots, true /* do_marking */); - process_strong_roots(false, // no scoping; this is parallel code so, &buf_scan_non_heap_roots, - &scan_code_roots, scan_klasses ); @@ -5180,12 +5180,6 @@ g1_process_strong_roots(bool is_scavenging, _process_strong_tasks->all_tasks_completed(); } -void -G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure) { - CodeBlobToOopClosure roots_in_blobs(root_closure, /*do_marking=*/ false); - SharedHeap::process_weak_roots(root_closure, &roots_in_blobs); -} - class G1StringSymbolTableUnlinkTask : public AbstractGangTask { private: BoolObjectClosure* _is_alive; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 07bbe275788..45caab039ea 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -833,11 +833,6 @@ protected: G1KlassScanClosure* scan_klasses, int worker_i); - // Apply "blk" to all the weak roots of the system. These include - // JNI weak roots, the code cache, system dictionary, symbol table, - // string table, and referents of reachable weak refs. - void g1_process_weak_roots(OopClosure* root_closure); - // Frees a non-humongous region by initializing its contents and // adding it to the free list that's passed as a parameter (this is // usually a local list which will be appended to the master free diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp index 2cc0f46a2cc..cee1cfd047a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @@ -133,7 +133,6 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, sh->process_strong_roots(true, // activate StrongRootsScope SharedHeap::SO_SystemClasses, &GenMarkSweep::follow_root_closure, - &GenMarkSweep::follow_code_root_closure, &GenMarkSweep::follow_klass_closure); // Process reference objects found during marking @@ -307,9 +306,8 @@ void G1MarkSweep::mark_sweep_phase3() { ClassLoaderDataGraph::clear_claimed_marks(); sh->process_strong_roots(true, // activate StrongRootsScope - SharedHeap::SO_AllClasses, + SharedHeap::SO_AllClasses | SharedHeap::SO_AllCodeCache, &GenMarkSweep::adjust_pointer_closure, - NULL, // do not touch code cache here &GenMarkSweep::adjust_klass_closure); assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity"); @@ -317,7 +315,7 @@ void G1MarkSweep::mark_sweep_phase3() { // Now adjust pointers in remaining weak roots. (All of which should // have been cleared if they pointed to non-surviving objects.) - g1h->g1_process_weak_roots(&GenMarkSweep::adjust_pointer_closure); + sh->process_weak_roots(&GenMarkSweep::adjust_pointer_closure); GenMarkSweep::adjust_marks(); diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index d97cc0dceb0..cc926949990 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -621,7 +621,6 @@ void ParNewGenTask::work(uint worker_id) { false, // no scope; this is parallel code SharedHeap::ScanningOption(so), &par_scan_state.to_space_root_closure(), - true, // walk *all* scavengable nmethods &par_scan_state.older_gen_closure(), &klass_scan_closure); par_scan_state.end_strong_roots(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp index 1bc3ea46a3e..67d8a5ac8ec 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp @@ -47,7 +47,6 @@ STWGCTimer* MarkSweep::_gc_timer = NULL; SerialOldTracer* MarkSweep::_gc_tracer = NULL; MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; -CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true); void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); } void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp index 38fc8e70589..1857c2a3acc 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp @@ -143,7 +143,6 @@ class MarkSweep : AllStatic { // Public closures static IsAliveClosure is_alive; static FollowRootClosure follow_root_closure; - static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure static MarkAndPushClosure mark_and_push_closure; static FollowKlassClosure follow_klass_closure; static FollowStackClosure follow_stack_closure; diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index 1e3cb9aaa3c..b4cf451f10e 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -626,7 +626,6 @@ void DefNewGeneration::collect(bool full, true, // activate StrongRootsScope SharedHeap::ScanningOption(so), &fsc_with_no_gc_barrier, - true, // walk *all* scavengable nmethods &fsc_with_gc_barrier, &klass_scan_closure); diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 5e0572e4ba7..be4ad6945dd 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -594,20 +594,12 @@ gen_process_strong_roots(int level, bool activate_scope, SharedHeap::ScanningOption so, OopsInGenClosure* not_older_gens, - bool do_code_roots, OopsInGenClosure* older_gens, KlassClosure* klass_closure) { // General strong roots. - if (!do_code_roots) { - SharedHeap::process_strong_roots(activate_scope, so, - not_older_gens, NULL, klass_closure); - } else { - bool do_code_marking = (activate_scope || nmethod::oops_do_marking_is_active()); - CodeBlobToOopClosure code_roots(not_older_gens, /*do_marking=*/ do_code_marking); - SharedHeap::process_strong_roots(activate_scope, so, - not_older_gens, &code_roots, klass_closure); - } + SharedHeap::process_strong_roots(activate_scope, so, + not_older_gens, klass_closure); if (younger_gens_as_roots) { if (!_gen_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { @@ -629,9 +621,8 @@ gen_process_strong_roots(int level, _gen_process_strong_tasks->all_tasks_completed(); } -void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure, - CodeBlobClosure* code_roots) { - SharedHeap::process_weak_roots(root_closure, code_roots); +void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) { + SharedHeap::process_weak_roots(root_closure); // "Local" "weak" refs for (int i = 0; i < _n_gens; i++) { _gens[i]->ref_processor()->weak_oops_do(root_closure); diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index 7bea23d68e4..f687a1c97e6 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -414,15 +414,13 @@ public: bool activate_scope, SharedHeap::ScanningOption so, OopsInGenClosure* not_older_gens, - bool do_code_roots, OopsInGenClosure* older_gens, KlassClosure* klass_closure); - // Apply "blk" to all the weak roots of the system. These include - // JNI weak roots, the code cache, system dictionary, symbol table, - // string table, and referents of reachable weak refs. - void gen_process_weak_roots(OopClosure* root_closure, - CodeBlobClosure* code_roots); + // Apply "root_closure" to all the weak roots of the system. + // These include JNI weak roots, string table, + // and referents of reachable weak refs. + void gen_process_weak_roots(OopClosure* root_closure); // Set the saved marks of generations, if that makes sense. // In particular, if any generation might iterate over the oops diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp index 2ae8b3dc6e2..9582ba2480f 100644 --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp @@ -212,7 +212,6 @@ void GenMarkSweep::mark_sweep_phase1(int level, true, // activate StrongRootsScope SharedHeap::SO_SystemClasses, &follow_root_closure, - true, // walk code active on stacks &follow_root_closure, &follow_klass_closure); @@ -295,18 +294,12 @@ void GenMarkSweep::mark_sweep_phase3(int level) { gch->gen_process_strong_roots(level, false, // Younger gens are not roots. true, // activate StrongRootsScope - SharedHeap::SO_AllClasses, + SharedHeap::SO_AllClasses | SharedHeap::SO_AllCodeCache, &adjust_pointer_closure, - false, // do not walk code &adjust_pointer_closure, &adjust_klass_closure); - // Now adjust pointers in remaining weak roots. (All of which should - // have been cleared if they pointed to non-surviving objects.) - CodeBlobToOopClosure adjust_code_pointer_closure(&adjust_pointer_closure, - /*do_marking=*/ false); - gch->gen_process_weak_roots(&adjust_pointer_closure, - &adjust_code_pointer_closure); + gch->gen_process_weak_roots(&adjust_pointer_closure); adjust_marks(); GenAdjustPointersClosure blk; diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index 2dbf43ef156..43c8503f1fc 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -139,7 +139,6 @@ SharedHeap::StrongRootsScope::~StrongRootsScope() { void SharedHeap::process_strong_roots(bool activate_scope, ScanningOption so, OopClosure* roots, - CodeBlobClosure* code_roots, KlassClosure* klass_closure) { StrongRootsScope srs(this, activate_scope); @@ -156,15 +155,17 @@ void SharedHeap::process_strong_roots(bool activate_scope, if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do)) JNIHandles::oops_do(roots); + CodeBlobToOopClosure code_roots(roots, true); + CLDToOopClosure roots_from_clds(roots); // If we limit class scanning to SO_SystemClasses we need to apply a CLD closure to // CLDs which are strongly reachable from the thread stacks. CLDToOopClosure* roots_from_clds_p = ((so & SO_SystemClasses) ? &roots_from_clds : NULL); // All threads execute this; the individual threads are task groups. if (CollectedHeap::use_parallel_gc_threads()) { - Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, code_roots); + Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, &code_roots); } else { - Threads::oops_do(roots, roots_from_clds_p, code_roots); + Threads::oops_do(roots, roots_from_clds_p, &code_roots); } if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do)) @@ -206,17 +207,17 @@ void SharedHeap::process_strong_roots(bool activate_scope, if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) { if (so & SO_ScavengeCodeCache) { - assert(code_roots != NULL, "must supply closure for code cache"); + assert(&code_roots != NULL, "must supply closure for code cache"); // We only visit parts of the CodeCache when scavenging. - CodeCache::scavenge_root_nmethods_do(code_roots); + CodeCache::scavenge_root_nmethods_do(&code_roots); } if (so & SO_AllCodeCache) { - assert(code_roots != NULL, "must supply closure for code cache"); + assert(&code_roots != NULL, "must supply closure for code cache"); // CMSCollector uses this to do intermediate-strength collections. // We scan the entire code cache, since CodeCache::do_unloading is not called. - CodeCache::blobs_do(code_roots); + CodeCache::blobs_do(&code_roots); } // Verify that the code cache contents are not subject to // movement by a scavenging collection. @@ -233,12 +234,10 @@ public: }; static AlwaysTrueClosure always_true; -void SharedHeap::process_weak_roots(OopClosure* root_closure, - CodeBlobClosure* code_roots) { +void SharedHeap::process_weak_roots(OopClosure* root_closure) { // Global (weak) JNI handles JNIHandles::weak_oops_do(&always_true, root_closure); - CodeCache::blobs_do(code_roots); StringTable::oops_do(root_closure); } diff --git a/hotspot/src/share/vm/memory/sharedHeap.hpp b/hotspot/src/share/vm/memory/sharedHeap.hpp index 398e593cc10..62669cf86e4 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.hpp +++ b/hotspot/src/share/vm/memory/sharedHeap.hpp @@ -238,14 +238,11 @@ public: void process_strong_roots(bool activate_scope, ScanningOption so, OopClosure* roots, - CodeBlobClosure* code_roots, KlassClosure* klass_closure); - // Apply "blk" to all the weak roots of the system. These include - // JNI weak roots, the code cache, system dictionary, symbol table, - // string table. - void process_weak_roots(OopClosure* root_closure, - CodeBlobClosure* code_roots); + // Apply "root_closure" to all the weak roots of the system. + // These include JNI weak roots and string table. + void process_weak_roots(OopClosure* root_closure); // The functions below are helper functions that a subclass of // "SharedHeap" can use in the implementation of its virtual @@ -275,4 +272,8 @@ public: size_t capacity); }; +inline SharedHeap::ScanningOption operator|(SharedHeap::ScanningOption so0, SharedHeap::ScanningOption so1) { + return static_cast(static_cast(so0) | static_cast(so1)); +} + #endif // SHARE_VM_MEMORY_SHAREDHEAP_HPP From 2a5c51998d9dc9703aaad5c5be7e7536b7105865 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 14 Feb 2014 09:29:56 +0100 Subject: [PATCH 138/265] 8034764: Use process_strong_roots to adjust the StringTable Reviewed-by: tschatzl, brutisso --- hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp | 2 +- hotspot/src/share/vm/memory/genMarkSweep.cpp | 2 +- hotspot/src/share/vm/memory/sharedHeap.cpp | 2 -- hotspot/src/share/vm/memory/sharedHeap.hpp | 3 +-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp index cee1cfd047a..dee7ce0b72e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @@ -306,7 +306,7 @@ void G1MarkSweep::mark_sweep_phase3() { ClassLoaderDataGraph::clear_claimed_marks(); sh->process_strong_roots(true, // activate StrongRootsScope - SharedHeap::SO_AllClasses | SharedHeap::SO_AllCodeCache, + SharedHeap::SO_AllClasses | SharedHeap::SO_Strings | SharedHeap::SO_AllCodeCache, &GenMarkSweep::adjust_pointer_closure, &GenMarkSweep::adjust_klass_closure); diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp index 9582ba2480f..80a35d10e2c 100644 --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp @@ -294,7 +294,7 @@ void GenMarkSweep::mark_sweep_phase3(int level) { gch->gen_process_strong_roots(level, false, // Younger gens are not roots. true, // activate StrongRootsScope - SharedHeap::SO_AllClasses | SharedHeap::SO_AllCodeCache, + SharedHeap::SO_AllClasses | SharedHeap::SO_Strings | SharedHeap::SO_AllCodeCache, &adjust_pointer_closure, &adjust_pointer_closure, &adjust_klass_closure); diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index 43c8503f1fc..9de74e25c7c 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -237,8 +237,6 @@ static AlwaysTrueClosure always_true; void SharedHeap::process_weak_roots(OopClosure* root_closure) { // Global (weak) JNI handles JNIHandles::weak_oops_do(&always_true, root_closure); - - StringTable::oops_do(root_closure); } void SharedHeap::set_barrier_set(BarrierSet* bs) { diff --git a/hotspot/src/share/vm/memory/sharedHeap.hpp b/hotspot/src/share/vm/memory/sharedHeap.hpp index 62669cf86e4..21d6755d9d3 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.hpp +++ b/hotspot/src/share/vm/memory/sharedHeap.hpp @@ -240,8 +240,7 @@ public: OopClosure* roots, KlassClosure* klass_closure); - // Apply "root_closure" to all the weak roots of the system. - // These include JNI weak roots and string table. + // Apply "root_closure" to the JNI weak roots.. void process_weak_roots(OopClosure* root_closure); // The functions below are helper functions that a subclass of From 2b8f41202aec30473a6a1deed52a95b4185aa7ff Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 11 Feb 2014 09:34:50 +0100 Subject: [PATCH 139/265] 8034171: Remove use of template template parameters from binaryTreeDictionary Reviewed-by: mgerdin, jmasa --- .../compactibleFreeListSpace.cpp | 8 +- .../share/vm/memory/binaryTreeDictionary.cpp | 227 +++++++++--------- .../share/vm/memory/binaryTreeDictionary.hpp | 32 +-- hotspot/src/share/vm/memory/metaspace.cpp | 16 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 2 +- 5 files changed, 136 insertions(+), 149 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 58a2d871317..d2aae84697d 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -1704,8 +1704,8 @@ CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { _dictionary->return_chunk(chunk); #ifndef PRODUCT if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { - TreeChunk* tc = TreeChunk::as_TreeChunk(chunk); - TreeList* tl = tc->list(); + TreeChunk >* tc = TreeChunk >::as_TreeChunk(chunk); + TreeList >* tl = tc->list(); tl->verify_stats(); } #endif // PRODUCT @@ -2515,10 +2515,10 @@ void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { #ifndef PRODUCT void CompactibleFreeListSpace::check_free_list_consistency() const { - assert((TreeChunk::min_size() <= IndexSetSize), + assert((TreeChunk >::min_size() <= IndexSetSize), "Some sizes can't be allocated without recourse to" " linear allocation buffers"); - assert((TreeChunk::min_size()*HeapWordSize == sizeof(TreeChunk)), + assert((TreeChunk >::min_size()*HeapWordSize == sizeof(TreeChunk >)), "else MIN_TREE_CHUNK_SIZE is wrong"); assert(IndexSetStart != 0, "IndexSetStart not initialized"); assert(IndexSetStride != 0, "IndexSetStride not initialized"); diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 68b97e9f0d3..8198c2f927c 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -44,16 +44,16 @@ // This is currently used in the Concurrent Mark&Sweep implementation. //////////////////////////////////////////////////////////////////////////////// -template class FreeList_t> +template size_t TreeChunk::_min_tree_chunk_size = sizeof(TreeChunk)/HeapWordSize; -template class FreeList_t> +template TreeChunk* TreeChunk::as_TreeChunk(Chunk_t* fc) { // Do some assertion checking here. return (TreeChunk*) fc; } -template class FreeList_t> +template void TreeChunk::verify_tree_chunk_list() const { TreeChunk* nextTC = (TreeChunk*)next(); if (prev() != NULL) { // interior list node shouldn't have tree fields @@ -67,11 +67,11 @@ void TreeChunk::verify_tree_chunk_list() const { } } -template class FreeList_t> +template TreeList::TreeList() : _parent(NULL), _left(NULL), _right(NULL) {} -template class FreeList_t> +template TreeList* TreeList::as_TreeList(TreeChunk* tc) { // This first free chunk in the list will be the tree list. @@ -88,20 +88,7 @@ TreeList::as_TreeList(TreeChunk* tc) { return tl; } - -template class FreeList_t> -TreeList* -get_chunk(size_t size, enum FreeBlockDictionary::Dither dither) { - FreeBlockDictionary::verify_par_locked(); - Chunk_t* res = get_chunk_from_tree(size, dither); - assert(res == NULL || res->is_free(), - "Should be returning a free chunk"); - assert(dither != FreeBlockDictionary::exactly || - res->size() == size, "Not correct size"); - return res; -} - -template class FreeList_t> +template TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) { TreeChunk* tc = (TreeChunk*) addr; @@ -125,17 +112,17 @@ TreeList::as_TreeList(HeapWord* addr, size_t size) { // an over populated size. The general get_better_list() just returns // the current list. template <> -TreeList* -TreeList::get_better_list( - BinaryTreeDictionary* dictionary) { +TreeList >* +TreeList >::get_better_list( + BinaryTreeDictionary >* dictionary) { // A candidate chunk has been found. If it is already under // populated, get a chunk associated with the hint for this // chunk. - TreeList* curTL = this; + TreeList >* curTL = this; if (surplus() <= 0) { /* Use the hint to find a size with a surplus, and reset the hint. */ - TreeList* hintTL = this; + TreeList >* hintTL = this; while (hintTL->hint() != 0) { assert(hintTL->hint() > hintTL->size(), "hint points in the wrong direction"); @@ -163,14 +150,14 @@ TreeList::get_better_list( } #endif // INCLUDE_ALL_GCS -template class FreeList_t> +template TreeList* TreeList::get_better_list( BinaryTreeDictionary* dictionary) { return this; } -template class FreeList_t> +template TreeList* TreeList::remove_chunk_replace_if_needed(TreeChunk* tc) { TreeList* retTL = this; @@ -286,7 +273,7 @@ TreeList* TreeList::remove_chunk_repla return retTL; } -template class FreeList_t> +template void TreeList::return_chunk_at_tail(TreeChunk* chunk) { assert(chunk != NULL, "returning NULL chunk"); assert(chunk->list() == this, "list should be set for chunk"); @@ -301,7 +288,7 @@ void TreeList::return_chunk_at_tail(TreeChunklink_tail(chunk); assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list"); - FreeList_t::increment_count(); + FreeList_t::increment_count(); debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));) assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); @@ -311,7 +298,7 @@ void TreeList::return_chunk_at_tail(TreeChunk is embedded in the first TreeChunk in the // list. See the definition of TreeChunk. -template class FreeList_t> +template void TreeList::return_chunk_at_head(TreeChunk* chunk) { assert(chunk->list() == this, "list should be set for chunk"); assert(head() != NULL, "The tree list is embedded in the first chunk"); @@ -329,13 +316,13 @@ void TreeList::return_chunk_at_head(TreeChunklink_after(chunk); assert(!head() || size() == head()->size(), "Wrong sized chunk in list"); - FreeList_t::increment_count(); + FreeList_t::increment_count(); debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));) assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); } -template class FreeList_t> +template void TreeChunk::assert_is_mangled() const { assert((ZapUnusedHeapArea && SpaceMangler::is_mangled((HeapWord*) Chunk_t::size_addr()) && @@ -345,14 +332,14 @@ void TreeChunk::assert_is_mangled() const { "Space should be clear or mangled"); } -template class FreeList_t> +template TreeChunk* TreeList::head_as_TreeChunk() { assert(head() == NULL || (TreeChunk::as_TreeChunk(head())->list() == this), "Wrong type of chunk?"); return TreeChunk::as_TreeChunk(head()); } -template class FreeList_t> +template TreeChunk* TreeList::first_available() { assert(head() != NULL, "The head of the list cannot be NULL"); Chunk_t* fc = head()->next(); @@ -369,7 +356,7 @@ TreeChunk* TreeList::first_available() // Returns the block with the largest heap address amongst // those in the list for this size; potentially slow and expensive, // use with caution! -template class FreeList_t> +template TreeChunk* TreeList::largest_address() { assert(head() != NULL, "The head of the list cannot be NULL"); Chunk_t* fc = head()->next(); @@ -392,7 +379,7 @@ TreeChunk* TreeList::largest_address() return retTC; } -template class FreeList_t> +template BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr) { assert((mr.byte_size() > min_size()), "minimum chunk size"); @@ -405,17 +392,17 @@ BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr) { assert(total_free_blocks() == 1, "reset check failed"); } -template class FreeList_t> +template void BinaryTreeDictionary::inc_total_size(size_t inc) { _total_size = _total_size + inc; } -template class FreeList_t> +template void BinaryTreeDictionary::dec_total_size(size_t dec) { _total_size = _total_size - dec; } -template class FreeList_t> +template void BinaryTreeDictionary::reset(MemRegion mr) { assert((mr.byte_size() > min_size()), "minimum chunk size"); set_root(TreeList::as_TreeList(mr.start(), mr.word_size())); @@ -423,13 +410,13 @@ void BinaryTreeDictionary::reset(MemRegion mr) { set_total_free_blocks(1); } -template class FreeList_t> +template void BinaryTreeDictionary::reset(HeapWord* addr, size_t byte_size) { MemRegion mr(addr, heap_word_size(byte_size)); reset(mr); } -template class FreeList_t> +template void BinaryTreeDictionary::reset() { set_root(NULL); set_total_size(0); @@ -437,7 +424,7 @@ void BinaryTreeDictionary::reset() { } // Get a free block of size at least size from tree, or NULL. -template class FreeList_t> +template TreeChunk* BinaryTreeDictionary::get_chunk_from_tree( size_t size, @@ -496,7 +483,7 @@ BinaryTreeDictionary::get_chunk_from_tree( return retTC; } -template class FreeList_t> +template TreeList* BinaryTreeDictionary::find_list(size_t size) const { TreeList* curTL; for (curTL = root(); curTL != NULL;) { @@ -515,7 +502,7 @@ TreeList* BinaryTreeDictionary::find_l } -template class FreeList_t> +template bool BinaryTreeDictionary::verify_chunk_in_free_list(Chunk_t* tc) const { size_t size = tc->size(); TreeList* tl = find_list(size); @@ -526,7 +513,7 @@ bool BinaryTreeDictionary::verify_chunk_in_free_list(Chunk_ } } -template class FreeList_t> +template Chunk_t* BinaryTreeDictionary::find_largest_dict() const { TreeList *curTL = root(); if (curTL != NULL) { @@ -541,7 +528,7 @@ Chunk_t* BinaryTreeDictionary::find_largest_dict() const { // chunk in a list on a tree node, just unlink it. // If it is the last chunk in the list (the next link is NULL), // remove the node and repair the tree. -template class FreeList_t> +template TreeChunk* BinaryTreeDictionary::remove_chunk_from_tree(TreeChunk* tc) { assert(tc != NULL, "Should not call with a NULL chunk"); @@ -682,7 +669,7 @@ BinaryTreeDictionary::remove_chunk_from_tree(TreeChunk class FreeList_t> +template TreeList* BinaryTreeDictionary::remove_tree_minimum(TreeList* tl) { assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree"); // locate the subtree minimum by walking down left branches @@ -717,7 +704,7 @@ TreeList* BinaryTreeDictionary::remove return curTL; } -template class FreeList_t> +template void BinaryTreeDictionary::insert_chunk_in_tree(Chunk_t* fc) { TreeList *curTL, *prevTL; size_t size = fc->size(); @@ -783,7 +770,7 @@ void BinaryTreeDictionary::insert_chunk_in_tree(Chunk_t* fc } } -template class FreeList_t> +template size_t BinaryTreeDictionary::max_chunk_size() const { FreeBlockDictionary::verify_par_locked(); TreeList* tc = root(); @@ -792,7 +779,7 @@ size_t BinaryTreeDictionary::max_chunk_size() const { return tc->size(); } -template class FreeList_t> +template size_t BinaryTreeDictionary::total_list_length(TreeList* tl) const { size_t res; res = tl->count(); @@ -805,7 +792,7 @@ size_t BinaryTreeDictionary::total_list_length(TreeList class FreeList_t> +template size_t BinaryTreeDictionary::total_size_in_tree(TreeList* tl) const { if (tl == NULL) return 0; @@ -814,7 +801,7 @@ size_t BinaryTreeDictionary::total_size_in_tree(TreeListright()); } -template class FreeList_t> +template double BinaryTreeDictionary::sum_of_squared_block_sizes(TreeList* const tl) const { if (tl == NULL) { return 0.0; @@ -826,7 +813,7 @@ double BinaryTreeDictionary::sum_of_squared_block_sizes(Tre return curr; } -template class FreeList_t> +template size_t BinaryTreeDictionary::total_free_blocks_in_tree(TreeList* tl) const { if (tl == NULL) return 0; @@ -835,14 +822,14 @@ size_t BinaryTreeDictionary::total_free_blocks_in_tree(Tree total_free_blocks_in_tree(tl->right()); } -template class FreeList_t> +template size_t BinaryTreeDictionary::num_free_blocks() const { assert(total_free_blocks_in_tree(root()) == total_free_blocks(), "_total_free_blocks inconsistency"); return total_free_blocks(); } -template class FreeList_t> +template size_t BinaryTreeDictionary::tree_height_helper(TreeList* tl) const { if (tl == NULL) return 0; @@ -850,12 +837,12 @@ size_t BinaryTreeDictionary::tree_height_helper(TreeListright())); } -template class FreeList_t> +template size_t BinaryTreeDictionary::tree_height() const { return tree_height_helper(root()); } -template class FreeList_t> +template size_t BinaryTreeDictionary::total_nodes_helper(TreeList* tl) const { if (tl == NULL) { return 0; @@ -864,18 +851,18 @@ size_t BinaryTreeDictionary::total_nodes_helper(TreeListright()); } -template class FreeList_t> +template size_t BinaryTreeDictionary::total_nodes_in_tree(TreeList* tl) const { return total_nodes_helper(root()); } -template class FreeList_t> +template void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){} #if INCLUDE_ALL_GCS template <> -void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ - TreeList* nd = find_list(size); +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) { + TreeList >* nd = find_list(size); if (nd) { if (split) { if (birth) { @@ -903,7 +890,7 @@ void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool b } #endif // INCLUDE_ALL_GCS -template class FreeList_t> +template bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { // For the general type of freelists, encourage coalescing by // returning true. @@ -915,7 +902,7 @@ template <> bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; - TreeList* list_of_size = find_list(size); + TreeList >* list_of_size = find_list(size); // None of requested size implies overpopulated. return list_of_size == NULL || list_of_size->coal_desired() <= 0 || list_of_size->count() > list_of_size->coal_desired(); @@ -928,15 +915,15 @@ bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { // do_tree() walks the nodes in the binary tree applying do_list() // to each list at each node. -template class FreeList_t> +template class TreeCensusClosure : public StackObj { protected: - virtual void do_list(FreeList_t* fl) = 0; + virtual void do_list(FreeList_t* fl) = 0; public: virtual void do_tree(TreeList* tl) = 0; }; -template class FreeList_t> +template class AscendTreeCensusClosure : public TreeCensusClosure { public: void do_tree(TreeList* tl) { @@ -948,7 +935,7 @@ class AscendTreeCensusClosure : public TreeCensusClosure { } }; -template class FreeList_t> +template class DescendTreeCensusClosure : public TreeCensusClosure { public: void do_tree(TreeList* tl) { @@ -962,7 +949,7 @@ class DescendTreeCensusClosure : public TreeCensusClosure { // For each list in the tree, calculate the desired, desired // coalesce, count before sweep, and surplus before sweep. -template class FreeList_t> +template class BeginSweepClosure : public AscendTreeCensusClosure { double _percentage; float _inter_sweep_current; @@ -995,16 +982,16 @@ class BeginSweepClosure : public AscendTreeCensusClosure { // Similar to TreeCensusClosure but searches the // tree and returns promptly when found. -template class FreeList_t> +template class TreeSearchClosure : public StackObj { protected: - virtual bool do_list(FreeList_t* fl) = 0; + virtual bool do_list(FreeList_t* fl) = 0; public: virtual bool do_tree(TreeList* tl) = 0; }; #if 0 // Don't need this yet but here for symmetry. -template class FreeList_t> +template class AscendTreeSearchClosure : public TreeSearchClosure { public: bool do_tree(TreeList* tl) { @@ -1018,7 +1005,7 @@ class AscendTreeSearchClosure : public TreeSearchClosure { }; #endif -template class FreeList_t> +template class DescendTreeSearchClosure : public TreeSearchClosure { public: bool do_tree(TreeList* tl) { @@ -1033,14 +1020,14 @@ class DescendTreeSearchClosure : public TreeSearchClosure { // Searches the tree for a chunk that ends at the // specified address. -template class FreeList_t> +template class EndTreeSearchClosure : public DescendTreeSearchClosure { HeapWord* _target; Chunk_t* _found; public: EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {} - bool do_list(FreeList_t* fl) { + bool do_list(FreeList_t* fl) { Chunk_t* item = fl->head(); while (item != NULL) { if (item->end() == (uintptr_t*) _target) { @@ -1054,7 +1041,7 @@ class EndTreeSearchClosure : public DescendTreeSearchClosure class FreeList_t> +template Chunk_t* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const { EndTreeSearchClosure etsc(target); bool found_target = etsc.do_tree(root()); @@ -1063,7 +1050,7 @@ Chunk_t* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* return etsc.found(); } -template class FreeList_t> +template void BinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent, float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, @@ -1075,32 +1062,32 @@ void BinaryTreeDictionary::begin_sweep_dict_census(double c // Closures and methods for calculating total bytes returned to the // free lists in the tree. #ifndef PRODUCT -template class FreeList_t> +template class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure { public: - void do_list(FreeList_t* fl) { + void do_list(FreeList_t* fl) { fl->set_returned_bytes(0); } }; -template class FreeList_t> +template void BinaryTreeDictionary::initialize_dict_returned_bytes() { InitializeDictReturnedBytesClosure idrb; idrb.do_tree(root()); } -template class FreeList_t> +template class ReturnedBytesClosure : public AscendTreeCensusClosure { size_t _dict_returned_bytes; public: ReturnedBytesClosure() { _dict_returned_bytes = 0; } - void do_list(FreeList_t* fl) { + void do_list(FreeList_t* fl) { _dict_returned_bytes += fl->returned_bytes(); } size_t dict_returned_bytes() { return _dict_returned_bytes; } }; -template class FreeList_t> +template size_t BinaryTreeDictionary::sum_dict_returned_bytes() { ReturnedBytesClosure rbc; rbc.do_tree(root()); @@ -1109,17 +1096,17 @@ size_t BinaryTreeDictionary::sum_dict_returned_bytes() { } // Count the number of entries in the tree. -template class FreeList_t> +template class treeCountClosure : public DescendTreeCensusClosure { public: uint count; treeCountClosure(uint c) { count = c; } - void do_list(FreeList_t* fl) { + void do_list(FreeList_t* fl) { count++; } }; -template class FreeList_t> +template size_t BinaryTreeDictionary::total_count() { treeCountClosure ctc(0); ctc.do_tree(root()); @@ -1128,7 +1115,7 @@ size_t BinaryTreeDictionary::total_count() { #endif // PRODUCT // Calculate surpluses for the lists in the tree. -template class FreeList_t> +template class setTreeSurplusClosure : public AscendTreeCensusClosure { double percentage; public: @@ -1144,14 +1131,14 @@ class setTreeSurplusClosure : public AscendTreeCensusClosure class FreeList_t> +template void BinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) { setTreeSurplusClosure sts(splitSurplusPercent); sts.do_tree(root()); } // Set hints for the lists in the tree. -template class FreeList_t> +template class setTreeHintsClosure : public DescendTreeCensusClosure { size_t hint; public: @@ -1170,14 +1157,14 @@ class setTreeHintsClosure : public DescendTreeCensusClosure #endif // INCLUDE_ALL_GCS }; -template class FreeList_t> +template void BinaryTreeDictionary::set_tree_hints(void) { setTreeHintsClosure sth(0); sth.do_tree(root()); } // Save count before previous sweep and splits and coalesces. -template class FreeList_t> +template class clearTreeCensusClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} @@ -1192,14 +1179,14 @@ class clearTreeCensusClosure : public AscendTreeCensusClosure class FreeList_t> +template void BinaryTreeDictionary::clear_tree_census(void) { clearTreeCensusClosure ctc; ctc.do_tree(root()); } // Do reporting and post sweep clean up. -template class FreeList_t> +template void BinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) { // Does walking the tree 3 times hurt? set_tree_surplus(splitSurplusPercent); @@ -1211,7 +1198,7 @@ void BinaryTreeDictionary::end_sweep_dict_census(double spl } // Print summary statistics -template class FreeList_t> +template void BinaryTreeDictionary::report_statistics() const { FreeBlockDictionary::verify_par_locked(); gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n" @@ -1230,22 +1217,22 @@ void BinaryTreeDictionary::report_statistics() const { // Print census information - counts, births, deaths, etc. // for each list in the tree. Also print some summary // information. -template class FreeList_t> +template class PrintTreeCensusClosure : public AscendTreeCensusClosure { int _print_line; size_t _total_free; - FreeList_t _total; + FreeList_t _total; public: PrintTreeCensusClosure() { _print_line = 0; _total_free = 0; } - FreeList_t* total() { return &_total; } + FreeList_t* total() { return &_total; } size_t total_free() { return _total_free; } void do_list(FreeList* fl) { if (++_print_line >= 40) { - FreeList_t::print_labels_on(gclog_or_tty, "size"); + FreeList_t::print_labels_on(gclog_or_tty, "size"); _print_line = 0; } fl->print_on(gclog_or_tty); @@ -1256,7 +1243,7 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosure* fl) { if (++_print_line >= 40) { - FreeList_t::print_labels_on(gclog_or_tty, "size"); + FreeList_t::print_labels_on(gclog_or_tty, "size"); _print_line = 0; } fl->print_on(gclog_or_tty); @@ -1275,16 +1262,16 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosure class FreeList_t> +template void BinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); - FreeList_t::print_labels_on(gclog_or_tty, "size"); + FreeList_t::print_labels_on(gclog_or_tty, "size"); PrintTreeCensusClosure ptc; ptc.do_tree(root()); - FreeList_t* total = ptc.total(); - FreeList_t::print_labels_on(gclog_or_tty, " "); + FreeList_t* total = ptc.total(); + FreeList_t::print_labels_on(gclog_or_tty, " "); } #if INCLUDE_ALL_GCS @@ -1293,7 +1280,7 @@ void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList::print_labels_on(gclog_or_tty, "size"); - PrintTreeCensusClosure ptc; + PrintTreeCensusClosure > ptc; ptc.do_tree(root()); AdaptiveFreeList* total = ptc.total(); @@ -1311,7 +1298,7 @@ void AFLBinaryTreeDictionary::print_dict_census(void) const { } #endif // INCLUDE_ALL_GCS -template class FreeList_t> +template class PrintFreeListsClosure : public AscendTreeCensusClosure { outputStream* _st; int _print_line; @@ -1321,9 +1308,9 @@ class PrintFreeListsClosure : public AscendTreeCensusClosure* fl) { + void do_list(FreeList_t* fl) { if (++_print_line >= 40) { - FreeList_t::print_labels_on(_st, "size"); + FreeList_t::print_labels_on(_st, "size"); _print_line = 0; } fl->print_on(gclog_or_tty); @@ -1337,10 +1324,10 @@ class PrintFreeListsClosure : public AscendTreeCensusClosure class FreeList_t> +template void BinaryTreeDictionary::print_free_lists(outputStream* st) const { - FreeList_t::print_labels_on(st, "size"); + FreeList_t::print_labels_on(st, "size"); PrintFreeListsClosure pflc(st); pflc.do_tree(root()); } @@ -1349,7 +1336,7 @@ void BinaryTreeDictionary::print_free_lists(outputStream* s // . _root has no parent // . parent and child point to each other // . each node's key correctly related to that of its child(ren) -template class FreeList_t> +template void BinaryTreeDictionary::verify_tree() const { guarantee(root() == NULL || total_free_blocks() == 0 || total_size() != 0, "_total_size shouldn't be 0?"); @@ -1357,7 +1344,7 @@ void BinaryTreeDictionary::verify_tree() const { verify_tree_helper(root()); } -template class FreeList_t> +template size_t BinaryTreeDictionary::verify_prev_free_ptrs(TreeList* tl) { size_t ct = 0; for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) { @@ -1371,7 +1358,7 @@ size_t BinaryTreeDictionary::verify_prev_free_ptrs(TreeList // Note: this helper is recursive rather than iterative, so use with // caution on very deep trees; and watch out for stack overflow errors; // In general, to be used only for debugging. -template class FreeList_t> +template void BinaryTreeDictionary::verify_tree_helper(TreeList* tl) const { if (tl == NULL) return; @@ -1400,25 +1387,25 @@ void BinaryTreeDictionary::verify_tree_helper(TreeListright()); } -template class FreeList_t> +template void BinaryTreeDictionary::verify() const { verify_tree(); guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency"); } -template class TreeList; -template class BinaryTreeDictionary; -template class TreeChunk; +template class TreeList >; +template class BinaryTreeDictionary >; +template class TreeChunk >; -template class TreeList; -template class BinaryTreeDictionary; -template class TreeChunk; +template class TreeList >; +template class BinaryTreeDictionary >; +template class TreeChunk >; #if INCLUDE_ALL_GCS // Explicitly instantiate these types for FreeChunk. -template class TreeList; -template class BinaryTreeDictionary; -template class TreeChunk; +template class TreeList >; +template class BinaryTreeDictionary >; +template class TreeChunk >; #endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp index 1867ed2ae22..8377912f242 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp @@ -37,18 +37,18 @@ // A TreeList is a FreeList which can be used to maintain a // binary tree of free lists. -template class FreeList_t> class TreeChunk; -template class FreeList_t> class BinaryTreeDictionary; -template class FreeList_t> class AscendTreeCensusClosure; -template class FreeList_t> class DescendTreeCensusClosure; -template class FreeList_t> class DescendTreeSearchClosure; +template class TreeChunk; +template class BinaryTreeDictionary; +template class AscendTreeCensusClosure; +template class DescendTreeCensusClosure; +template class DescendTreeSearchClosure; class FreeChunk; template class AdaptiveFreeList; -typedef BinaryTreeDictionary AFLBinaryTreeDictionary; +typedef BinaryTreeDictionary > AFLBinaryTreeDictionary; -template class FreeList_t> -class TreeList : public FreeList_t { +template +class TreeList : public FreeList_t { friend class TreeChunk; friend class BinaryTreeDictionary; friend class AscendTreeCensusClosure; @@ -66,12 +66,12 @@ class TreeList : public FreeList_t { TreeList* right() const { return _right; } // Wrapper on call to base class, to get the template to compile. - Chunk_t* head() const { return FreeList_t::head(); } - Chunk_t* tail() const { return FreeList_t::tail(); } - void set_head(Chunk_t* head) { FreeList_t::set_head(head); } - void set_tail(Chunk_t* tail) { FreeList_t::set_tail(tail); } + Chunk_t* head() const { return FreeList_t::head(); } + Chunk_t* tail() const { return FreeList_t::tail(); } + void set_head(Chunk_t* head) { FreeList_t::set_head(head); } + void set_tail(Chunk_t* tail) { FreeList_t::set_tail(tail); } - size_t size() const { return FreeList_t::size(); } + size_t size() const { return FreeList_t::size(); } // Accessors for links in tree. @@ -90,7 +90,7 @@ class TreeList : public FreeList_t { void clear_left() { _left = NULL; } void clear_right() { _right = NULL; } void clear_parent() { _parent = NULL; } - void initialize() { clear_left(); clear_right(), clear_parent(); FreeList_t::initialize(); } + void initialize() { clear_left(); clear_right(), clear_parent(); FreeList_t::initialize(); } // For constructing a TreeList from a Tree chunk or // address and size. @@ -139,7 +139,7 @@ class TreeList : public FreeList_t { // on the free list for a node in the tree and is only removed if // it is the last chunk on the free list. -template class FreeList_t> +template class TreeChunk : public Chunk_t { friend class TreeList; TreeList* _list; @@ -173,7 +173,7 @@ class TreeChunk : public Chunk_t { }; -template class FreeList_t> +template class BinaryTreeDictionary: public FreeBlockDictionary { friend class VMStructs; size_t _total_size; diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 6105321c30f..9c3b48dc8f8 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -46,8 +46,8 @@ #include "utilities/copy.hpp" #include "utilities/debug.hpp" -typedef BinaryTreeDictionary BlockTreeDictionary; -typedef BinaryTreeDictionary ChunkTreeDictionary; +typedef BinaryTreeDictionary > BlockTreeDictionary; +typedef BinaryTreeDictionary > ChunkTreeDictionary; // Set this constant to enable slow integrity checking of the free chunk lists const bool metaspace_slow_verify = false; @@ -790,7 +790,7 @@ MetaWord* BlockFreelist::get_block(size_t word_size) { return NULL; } - if (word_size < TreeChunk::min_size()) { + if (word_size < TreeChunk >::min_size()) { // Dark matter. Too small for dictionary. return NULL; } @@ -810,7 +810,7 @@ MetaWord* BlockFreelist::get_block(size_t word_size) { MetaWord* new_block = (MetaWord*)free_block; assert(block_size >= word_size, "Incorrect size of block from freelist"); const size_t unused = block_size - word_size; - if (unused >= TreeChunk::min_size()) { + if (unused >= TreeChunk >::min_size()) { return_block(new_block + word_size, unused); } @@ -2240,7 +2240,7 @@ ChunkIndex ChunkManager::list_index(size_t size) { void SpaceManager::deallocate(MetaWord* p, size_t word_size) { assert_lock_strong(_lock); size_t raw_word_size = get_raw_word_size(word_size); - size_t min_size = TreeChunk::min_size(); + size_t min_size = TreeChunk >::min_size(); assert(raw_word_size >= min_size, err_msg("Should not deallocate dark matter " SIZE_FORMAT "<" SIZE_FORMAT, word_size, min_size)); block_freelists()->return_block(p, raw_word_size); @@ -2296,7 +2296,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { void SpaceManager::retire_current_chunk() { if (current_chunk() != NULL) { size_t remaining_words = current_chunk()->free_word_size(); - if (remaining_words >= TreeChunk::min_size()) { + if (remaining_words >= TreeChunk >::min_size()) { block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words); inc_used_metrics(remaining_words); } @@ -3279,7 +3279,7 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { assert(Thread::current()->is_VM_thread(), "should be the VM thread"); // Don't take Heap_lock MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); - if (word_size < TreeChunk::min_size()) { + if (word_size < TreeChunk >::min_size()) { // Dark matter. Too small for dictionary. #ifdef ASSERT Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); @@ -3294,7 +3294,7 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { } else { MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); - if (word_size < TreeChunk::min_size()) { + if (word_size < TreeChunk >::min_size()) { // Dark matter. Too small for dictionary. #ifdef ASSERT Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 0897c25183b..c1191a0562c 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -242,7 +242,7 @@ typedef TwoOopHashtable KlassTwoOopHashtable; typedef Hashtable KlassHashtable; typedef HashtableEntry KlassHashtableEntry; typedef TwoOopHashtable SymbolTwoOopHashtable; -typedef BinaryTreeDictionary MetablockTreeDictionary; +typedef BinaryTreeDictionary > MetablockTreeDictionary; //-------------------------------------------------------------------------------- // VM_STRUCTS From cde5c5862b70dd62d5269be4bd38ad3f079ea25c Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Tue, 11 Feb 2014 13:29:53 +0100 Subject: [PATCH 140/265] 8034188: OSR methods may not be recompiled at proper compilation level Remove_osr_nmethod doesn't check that it is the correct method Reviewed-by: kvn, iveresov --- hotspot/src/share/vm/oops/instanceKlass.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 7dee4f3dba3..c37f5ebb70c 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2711,7 +2711,7 @@ void InstanceKlass::remove_osr_nmethod(nmethod* n) { Method* m = n->method(); // Search for match while(cur != NULL && cur != n) { - if (TieredCompilation) { + if (TieredCompilation && m == cur->method()) { // Find max level before n max_level = MAX2(max_level, cur->comp_level()); } @@ -2733,7 +2733,9 @@ void InstanceKlass::remove_osr_nmethod(nmethod* n) { cur = next; while (cur != NULL) { // Find max level after n - max_level = MAX2(max_level, cur->comp_level()); + if (m == cur->method()) { + max_level = MAX2(max_level, cur->comp_level()); + } cur = cur->osr_link(); } m->set_highest_osr_comp_level(max_level); From 7f138c55021339aeceb8dbbfee8e5a4763dcef4d Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 11 Feb 2014 08:43:17 -0800 Subject: [PATCH 141/265] 7182040: volano29 limited by os resource on Linux - need better diagnostic message Changed message to "unable to create native thread: possibly out of memory or process/resource limits reached" Reviewed-by: dholmes, sla --- hotspot/src/share/vm/compiler/compileBroker.cpp | 2 +- .../vm/gc_implementation/shared/concurrentGCThread.cpp | 3 ++- hotspot/src/share/vm/prims/jvm.cpp | 4 ++-- hotspot/src/share/vm/runtime/os.cpp | 2 +- hotspot/src/share/vm/runtime/os.hpp | 7 +++++++ hotspot/src/share/vm/runtime/serviceThread.cpp | 3 ++- hotspot/src/share/vm/services/attachListener.cpp | 2 +- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 57eee0b91e3..536bca7851a 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -955,7 +955,7 @@ CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQue if (compiler_thread == NULL || compiler_thread->osthread() == NULL){ vm_exit_during_initialization("java.lang.OutOfMemoryError", - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } java_lang_Thread::set_thread(thread_oop(), compiler_thread); diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp index 0aba69e2a64..b0c6e95191a 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp @@ -31,6 +31,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/os.hpp" // CopyrightVersion 1.2 @@ -206,7 +207,7 @@ SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) { // exceptions anyway, check and abort if this fails. if (res == NULL || res->osthread() == NULL) { vm_exit_during_initialization("java.lang.OutOfMemoryError", - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } java_lang_Thread::set_thread(thread_oop(), res); java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 1059783eb05..d1d7c3efbfe 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -2875,10 +2875,10 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } Thread::start(native_thread); diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 74617ab97e8..8615b6d4108 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -362,7 +362,7 @@ void os::signal_init() { // exceptions anyway, check and abort if this fails. if (signal_thread == NULL || signal_thread->osthread() == NULL) { vm_exit_during_initialization("java.lang.OutOfMemoryError", - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } java_lang_Thread::set_thread(thread_oop(), signal_thread); diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 54aeb012a49..0731663ddad 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -805,6 +805,10 @@ class os: AllStatic { #endif #ifdef TARGET_OS_ARCH_bsd_zero # include "os_bsd_zero.hpp" +#endif + +#ifndef OS_NATIVE_THREAD_CREATION_FAILED_MSG +#define OS_NATIVE_THREAD_CREATION_FAILED_MSG "unable to create native thread: possibly out of memory or process/resource limits reached" #endif public: @@ -829,6 +833,9 @@ class os: AllStatic { // Hint to the underlying OS that a task switch would not be good. // Void return because it's a hint and can fail. static void hint_no_preempt(); + static const char* native_thread_creation_failed_msg() { + return OS_NATIVE_THREAD_CREATION_FAILED_MSG; + } // Used at creation if requested by the diagnostic flag PauseAtStartup. // Causes the VM to wait until an external stimulus has been applied diff --git a/hotspot/src/share/vm/runtime/serviceThread.cpp b/hotspot/src/share/vm/runtime/serviceThread.cpp index 66d4572522f..3c1224abb2c 100644 --- a/hotspot/src/share/vm/runtime/serviceThread.cpp +++ b/hotspot/src/share/vm/runtime/serviceThread.cpp @@ -27,6 +27,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/serviceThread.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/os.hpp" #include "prims/jvmtiImpl.hpp" #include "services/gcNotifier.hpp" #include "services/diagnosticArgument.hpp" @@ -66,7 +67,7 @@ void ServiceThread::initialize() { // exceptions anyway, check and abort if this fails. if (thread == NULL || thread->osthread() == NULL) { vm_exit_during_initialization("java.lang.OutOfMemoryError", - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } java_lang_Thread::set_thread(thread_oop(), thread); diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index e7d8c380951..8551563f59f 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -532,7 +532,7 @@ void AttachListener::init() { // Check that thread and osthread were created if (listener_thread == NULL || listener_thread->osthread() == NULL) { vm_exit_during_initialization("java.lang.OutOfMemoryError", - "unable to create new native thread"); + os::native_thread_creation_failed_msg()); } java_lang_Thread::set_thread(thread_oop(), listener_thread); From a752b0b503712b63b3831ddbebc953b2b3c5cc80 Mon Sep 17 00:00:00 2001 From: Henry Jen Date: Tue, 11 Feb 2014 21:32:19 -0800 Subject: [PATCH 142/265] 8033215: clang: node.cpp:284 IDX_INIT macro use uninitialized field _out Reviewed-by: twisti, kvn --- hotspot/src/share/vm/opto/node.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 06e74b6d0f2..344f7f0fb8e 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -285,6 +285,10 @@ void DUIterator_Last::verify_step(uint num_edges) { #ifdef _MSC_VER // the IDX_INIT hack falls foul of warning C4355 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif // Out-of-line code from node constructors. // Executed only when extra debug info. is being passed around. @@ -468,6 +472,10 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, _in[6] = n6; if (n6 != NULL) n6->add_out((Node *)this); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + //------------------------------clone------------------------------------------ // Clone a Node. From b633a889a7e8e8885c4b4f6042d37c89a8b42b83 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Wed, 12 Feb 2014 09:37:18 -0800 Subject: [PATCH 143/265] 8030350: Enable additional compiler warnings for GCC Reviewed-by: dholmes, coleenp, erikj, tbell, ihse --- hotspot/make/bsd/makefiles/gcc.make | 4 ++-- hotspot/make/linux/makefiles/gcc.make | 2 +- hotspot/make/solaris/makefiles/gcc.make | 2 +- hotspot/src/os/bsd/vm/os_bsd.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 8f708eab3df..b6bca43e5bd 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -260,7 +260,7 @@ ifeq ($(USE_CLANG), true) WARNINGS_ARE_ERRORS += -Wno-empty-body endif -WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function -Wunused-value +WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function -Wformat=2 -Wno-error=format-nonliteral ifeq ($(USE_CLANG),) # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit @@ -289,7 +289,7 @@ CFLAGS += -fno-strict-aliasing # The flags to use for an Optimized g++ build ifeq ($(OS_VENDOR), Darwin) # use -Os by default, unless -O3 can be proved to be worth the cost, as per policy - # + # OPT_CFLAGS_DEFAULT ?= SIZE else OPT_CFLAGS_DEFAULT ?= SPEED diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index bc4a24c7787..daf6735ab33 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -214,7 +214,7 @@ ifeq ($(USE_CLANG), true) WARNINGS_ARE_ERRORS += -Wno-return-type -Wno-empty-body endif -WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function -Wunused-value +WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function -Wunused-value -Wformat=2 -Wno-error=format-nonliteral ifeq ($(USE_CLANG),) # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit diff --git a/hotspot/make/solaris/makefiles/gcc.make b/hotspot/make/solaris/makefiles/gcc.make index fe65ad4f5bf..627691c78f3 100644 --- a/hotspot/make/solaris/makefiles/gcc.make +++ b/hotspot/make/solaris/makefiles/gcc.make @@ -118,7 +118,7 @@ endif # Compiler warnings are treated as errors WARNINGS_ARE_ERRORS = -Werror # Enable these warnings. See 'info gcc' about details on these options -WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef +WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef -Wformat=2 -Wno-error=format-nonliteral CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS) # Special cases CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index cadf960b1ac..5be87da64eb 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1834,7 +1834,7 @@ void os::jvm_path(char *buf, jint buflen) { jrelib_p = buf + len; snprintf(jrelib_p, buflen-len, "/%s", COMPILER_VARIANT); if (0 != access(buf, F_OK)) { - snprintf(jrelib_p, buflen-len, ""); + snprintf(jrelib_p, buflen-len, "%s", ""); } // If the path exists within JAVA_HOME, add the JVM library name From a279dee28c0b68422e74e35b58e084781d963340 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 12 Feb 2014 22:08:43 +0400 Subject: [PATCH 144/265] 8023667: SA: ExceptionBlob and other C2 classes not available in client VM Ignore error of intialization of C2 only variables Reviewed-by: sla, dholmes --- .../classes/sun/jvm/hotspot/utilities/soql/sa.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js index a700f1bc6bd..9651e0ad4e2 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js @@ -804,6 +804,16 @@ delete tmp; // VM type to SA class map var vmType2Class = new Object(); +// C2 only classes +try{ + vmType2Class["ExceptionBlob"] = sapkg.code.ExceptionBlob; + vmType2Class["UncommonTrapBlob"] = sapkg.code.UncommonTrapBlob; +} catch(e) { + // Ignore exception. C2 specific objects might be not + // available in client VM +} + + // This is *not* exhaustive. Add more if needed. // code blobs vmType2Class["BufferBlob"] = sapkg.code.BufferBlob; @@ -812,10 +822,8 @@ vmType2Class["RuntimeStub"] = sapkg.code.RuntimeStub; vmType2Class["SafepointBlob"] = sapkg.code.SafepointBlob; vmType2Class["C2IAdapter"] = sapkg.code.C2IAdapter; vmType2Class["DeoptimizationBlob"] = sapkg.code.DeoptimizationBlob; -vmType2Class["ExceptionBlob"] = sapkg.code.ExceptionBlob; vmType2Class["I2CAdapter"] = sapkg.code.I2CAdapter; vmType2Class["OSRAdapter"] = sapkg.code.OSRAdapter; -vmType2Class["UncommonTrapBlob"] = sapkg.code.UncommonTrapBlob; vmType2Class["PCDesc"] = sapkg.code.PCDesc; // interpreter From 656746d828c0b7ee24d109ad81b9f0f53b5589f3 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 12 Feb 2014 23:39:53 +0400 Subject: [PATCH 145/265] 7127191: SA JSDB does not display native symbols correctly for transported Linux cores Better handle SA_ALTROOT Reviewed-by: sla, sspitsyn --- hotspot/agent/src/os/linux/libproc_impl.c | 79 +++++++++---------- .../debugger/linux/LinuxCDebugger.java | 36 +++------ .../sun/jvm/hotspot/utilities/soql/sa.js | 68 +++++++++------- 3 files changed, 91 insertions(+), 92 deletions(-) diff --git a/hotspot/agent/src/os/linux/libproc_impl.c b/hotspot/agent/src/os/linux/libproc_impl.c index 2ea0d0f88f9..a04bc37d1d7 100644 --- a/hotspot/agent/src/os/linux/libproc_impl.c +++ b/hotspot/agent/src/os/linux/libproc_impl.c @@ -29,54 +29,51 @@ #include #include "libproc_impl.h" -static const char* alt_root = NULL; -static int alt_root_len = -1; - #define SA_ALTROOT "SA_ALTROOT" -static void init_alt_root() { - if (alt_root_len == -1) { - alt_root = getenv(SA_ALTROOT); - if (alt_root) { - alt_root_len = strlen(alt_root); - } else { - alt_root_len = 0; - } - } -} - int pathmap_open(const char* name) { - int fd; - char alt_path[PATH_MAX + 1]; + static const char *alt_root = NULL; + static int alt_root_initialized = 0; - init_alt_root(); + int fd; + char alt_path[PATH_MAX + 1], *alt_path_end; + const char *s; - if (alt_root_len > 0) { - strcpy(alt_path, alt_root); - strcat(alt_path, name); - fd = open(alt_path, O_RDONLY); - if (fd >= 0) { - print_debug("path %s substituted for %s\n", alt_path, name); - return fd; - } + if (!alt_root_initialized) { + alt_root_initialized = -1; + alt_root = getenv(SA_ALTROOT); + } - if (strrchr(name, '/')) { - strcpy(alt_path, alt_root); - strcat(alt_path, strrchr(name, '/')); - fd = open(alt_path, O_RDONLY); - if (fd >= 0) { - print_debug("path %s substituted for %s\n", alt_path, name); - return fd; - } - } - } else { - fd = open(name, O_RDONLY); - if (fd >= 0) { - return fd; - } - } + if (alt_root == NULL) { + return open(name, O_RDONLY); + } - return -1; + strcpy(alt_path, alt_root); + alt_path_end = alt_path + strlen(alt_path); + + // Strip path items one by one and try to open file with alt_root prepended + s = name; + while (1) { + strcat(alt_path, s); + s += 1; + + fd = open(alt_path, O_RDONLY); + if (fd >= 0) { + print_debug("path %s substituted for %s\n", alt_path, name); + return fd; + } + + // Linker always put full path to solib to process, so we can rely + // on presence of /. If slash is not present, it means, that SOlib doesn't + // physically exist (e.g. linux-gate.so) and we fail opening it anyway + if ((s = strchr(s, '/')) == NULL) { + break; + } + + *alt_path_end = 0; + } + + return -1; } static bool _libsaproc_debug; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java index f2d947493ee..91d47c60e3f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java @@ -55,31 +55,21 @@ class LinuxCDebugger implements CDebugger { if (pc == null) { return null; } - List objs = getLoadObjectList(); - Object[] arr = objs.toArray(); - // load objects are sorted by base address, do binary search - int mid = -1; - int low = 0; - int high = arr.length - 1; - while (low <= high) { - mid = (low + high) >> 1; - LoadObject midVal = (LoadObject) arr[mid]; - long cmp = pc.minus(midVal.getBase()); - if (cmp < 0) { - high = mid - 1; - } else if (cmp > 0) { - long size = midVal.getSize(); - if (cmp >= size) { - low = mid + 1; - } else { - return (LoadObject) arr[mid]; - } - } else { // match found - return (LoadObject) arr[mid]; - } + /* Typically we have about ten loaded objects here. So no reason to do + sort/binary search here. Linear search gives us acceptable performance.*/ + + List objs = getLoadObjectList(); + + for (int i = 0; i < objs.size(); i++) { + LoadObject ob = (LoadObject) objs.get(i); + Address base = ob.getBase(); + long size = ob.getSize(); + if ( pc.greaterThanOrEqual(base) && pc.lessThan(base.addOffsetTo(size))) { + return ob; + } } - // no match found. + return null; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js index 9651e0ad4e2..14a8e9aa137 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js @@ -371,19 +371,23 @@ function sym2addr(dso, sym) { return sa.dbg.lookup(dso, sym); } -// returns the ClosestSymbol or null -function closestSymbolFor(addr) { - if (sa.cdbg == null) { +function loadObjectContainingPC(addr) { + if (sa.cdbg == null) { // no CDebugger support, return null return null; - } else { - var dso = sa.cdbg.loadObjectContainingPC(addr); - if (dso != null) { - return dso.closestSymbolToPC(addr); - } else { - return null; - } - } + } + + return sa.cdbg.loadObjectContainingPC(addr); +} + +// returns the ClosestSymbol or null +function closestSymbolFor(addr) { + var dso = loadObjectContainingPC(addr); + if (dso != null) { + return dso.closestSymbolToPC(addr); + } + + return null; } // Address-to-symbol @@ -884,21 +888,29 @@ function isOop(addr) { // returns description of given pointer as a String function whatis(addr) { - addr = any2addr(addr); - var ptrLoc = findPtr(addr); - if (ptrLoc.isUnknown()) { - var vmType = vmTypeof(addr); - if (vmType != null) { - return "pointer to " + vmType.name; - } else { - var sym = closestSymbolFor(addr); - if (sym != null) { - return sym.name + '+' + sym.offset; - } else { - return ptrLoc.toString(); - } - } - } else { - return ptrLoc.toString(); - } + addr = any2addr(addr); + var ptrLoc = findPtr(addr); + if (!ptrLoc.isUnknown()) { + return ptrLoc.toString(); + } + + var vmType = vmTypeof(addr); + if (vmType != null) { + return "pointer to " + vmType.name; + } + + var dso = loadObjectContainingPC(addr); + if (dso == null) { + return ptrLoc.toString(); + } + + var sym = dso.closestSymbolToPC(addr); + if (sym != null) { + return sym.name + '+' + sym.offset; + } + + var s = dso.getName(); + var p = s.lastIndexOf("/"); + var base = dso.getBase(); + return s.substring(p+1, s.length) + '+' + addr.minus(base); } From 56c2d62e5e040c692e976dfd9ed9c7c03be98b02 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Wed, 12 Feb 2014 20:40:02 +0100 Subject: [PATCH 146/265] 8034781: [TESTBUG] runtime/ClassFileUnsupportedClassFileVersion.java unable to find or load main class Passed empty string to ProcessBuilder which caused problems on Linux, fixed by checking string length Reviewed-by: lfoltan, sla, mseledtsov --- .../testlibrary/com/oracle/java/testlibrary/ProcessTools.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java index 4bc11f8bf5d..04293905824 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -154,7 +154,7 @@ public final class ProcessTools { if (addTestVmOptions) { String vmopts = System.getProperty("test.vm.opts"); - if (vmopts != null) { + if (vmopts != null && vmopts.length() > 0) { Collections.addAll(args, vmopts.split("\\s")); } } From afe8f1c904ccfd41d10648f04f41d60462b1b650 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 12 Feb 2014 12:01:45 -0800 Subject: [PATCH 147/265] 8028785: [parfait] warnings from b116 for hotspot.src.share.vm.prims: JNI exception pending Added JNI exception pending check in several files under src/share/vm/prims directory Reviewed-by: coleenp, minqi --- hotspot/src/share/vm/prims/jni.cpp | 15 +++++++++++++++ hotspot/src/share/vm/prims/unsafe.cpp | 5 +++++ hotspot/src/share/vm/prims/whitebox.cpp | 25 ++++++++++++++++++++----- hotspot/src/share/vm/prims/whitebox.hpp | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 5d3327d1c23..de225f997eb 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -4348,8 +4348,23 @@ static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) { // Get needed field and method IDs directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "", "(JI)V"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + directBufferSupportInitializeFailed = 1; + return false; + } directBufferAddressField = env->GetFieldID(bufferClass, "address", "J"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + directBufferSupportInitializeFailed = 1; + return false; + } bufferCapacityField = env->GetFieldID(bufferClass, "capacity", "I"); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + directBufferSupportInitializeFailed = 1; + return false; + } if ((directByteBufferConstructor == NULL) || (directBufferAddressField == NULL) || diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 2e432264b6e..5a5d7c93c47 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -858,6 +858,11 @@ static inline void throw_new(JNIEnv *env, const char *ename) { strcpy(buf, "java/lang/"); strcat(buf, ename); jclass cls = env->FindClass(buf); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", buf); + return; + } char* msg = NULL; env->ThrowNew(cls, msg); } diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 1cb799b3ea9..095ac20c3c9 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -316,9 +316,10 @@ WB_END WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + int result = 0; + CHECK_JNI_EXCEPTION_(env, result); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - int result = 0; nmethod* code; if (is_osr) { int bci = InvocationEntryBci; @@ -344,6 +345,7 @@ WB_END WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); @@ -355,6 +357,7 @@ WB_END WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); if (is_osr) { @@ -366,6 +369,7 @@ WB_END WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); return mh->queued_for_compilation(); @@ -373,6 +377,7 @@ WB_END WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, CompLevel_none); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); return (code != NULL ? code->comp_level() : CompLevel_none); @@ -380,6 +385,7 @@ WB_END WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION(env); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); if (is_osr) { mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox"); @@ -390,6 +396,7 @@ WB_END WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, InvocationEntryBci); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false); return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci); @@ -397,6 +404,7 @@ WB_END WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); bool result = mh->dont_inline(); mh->set_dont_inline(value == JNI_TRUE); @@ -414,6 +422,7 @@ WB_END WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); bool result = mh->force_inline(); mh->set_force_inline(value == JNI_TRUE); @@ -422,6 +431,7 @@ WB_END WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); MutexLockerEx mu(Compile_lock); @@ -430,6 +440,7 @@ WB_END WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION(env); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); MutexLockerEx mu(Compile_lock); MethodData* mdo = mh->method_data(); @@ -616,14 +627,18 @@ JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass)) bool result = true; // one by one registration natives for exception catching jclass exceptionKlass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string()); + CHECK_JNI_EXCEPTION(env); for (int i = 0, n = sizeof(methods) / sizeof(methods[0]); i < n; ++i) { if (env->RegisterNatives(wbclass, methods + i, 1) != 0) { result = false; - if (env->ExceptionCheck() && env->IsInstanceOf(env->ExceptionOccurred(), exceptionKlass)) { - // j.l.NoSuchMethodError is thrown when a method can't be found or a method is not native - // ignoring the exception - tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s", methods[i].name, methods[i].signature); + jthrowable throwable_obj = env->ExceptionOccurred(); + if (throwable_obj != NULL) { env->ExceptionClear(); + if (env->IsInstanceOf(throwable_obj, exceptionKlass)) { + // j.l.NoSuchMethodError is thrown when a method can't be found or a method is not native + // ignoring the exception + tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s", methods[i].name, methods[i].signature); + } } else { // register is failed w/o exception or w/ unexpected exception tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered", methods[i].name, methods[i].signature); diff --git a/hotspot/src/share/vm/prims/whitebox.hpp b/hotspot/src/share/vm/prims/whitebox.hpp index f78117414cf..42d00b2fcda 100644 --- a/hotspot/src/share/vm/prims/whitebox.hpp +++ b/hotspot/src/share/vm/prims/whitebox.hpp @@ -36,6 +36,22 @@ #define WB_END JNI_END #define WB_METHOD_DECLARE(result_type) extern "C" result_type JNICALL +#define CHECK_JNI_EXCEPTION_(env, value) \ + do { \ + if (env->ExceptionCheck()) { \ + env->ExceptionClear(); \ + return(value); \ + } \ + } while (0) + +#define CHECK_JNI_EXCEPTION(env) \ + do { \ + if (env->ExceptionCheck()) { \ + env->ExceptionClear(); \ + return; \ + } \ + } while (0) + class WhiteBox : public AllStatic { private: static bool _used; From 297485c528129bb0f132a3909dec1cded6e3b585 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 14 Feb 2014 09:50:17 -0800 Subject: [PATCH 148/265] 8034860: Fatal error due to incorrect thread state during nightly testing Use the HAS_PENDING_EXCEPTION and CLEAR_PENDING_EXCEPTION macros Reviewed-by: dholmes, coleenp, dcubed --- hotspot/src/share/vm/prims/whitebox.hpp | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/prims/whitebox.hpp b/hotspot/src/share/vm/prims/whitebox.hpp index 42d00b2fcda..a6e27b49055 100644 --- a/hotspot/src/share/vm/prims/whitebox.hpp +++ b/hotspot/src/share/vm/prims/whitebox.hpp @@ -36,20 +36,22 @@ #define WB_END JNI_END #define WB_METHOD_DECLARE(result_type) extern "C" result_type JNICALL -#define CHECK_JNI_EXCEPTION_(env, value) \ - do { \ - if (env->ExceptionCheck()) { \ - env->ExceptionClear(); \ - return(value); \ - } \ +#define CHECK_JNI_EXCEPTION_(env, value) \ + do { \ + JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ + if (HAS_PENDING_EXCEPTION) { \ + CLEAR_PENDING_EXCEPTION; \ + return(value); \ + } \ } while (0) -#define CHECK_JNI_EXCEPTION(env) \ - do { \ - if (env->ExceptionCheck()) { \ - env->ExceptionClear(); \ - return; \ - } \ +#define CHECK_JNI_EXCEPTION(env) \ + do { \ + JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ + if (HAS_PENDING_EXCEPTION) { \ + CLEAR_PENDING_EXCEPTION; \ + return; \ + } \ } while (0) class WhiteBox : public AllStatic { From c9b3cbbdcca37d679abaab7ece0bccb5c79fa28e Mon Sep 17 00:00:00 2001 From: Shanliang Jiang Date: Fri, 14 Feb 2014 16:17:22 +0100 Subject: [PATCH 149/265] 8007710: runtime/7158988/FieldMonitor.java fails with com.sun.jdi.VMDisconnectedException: Connection closed Reviewed-by: sla, jbachorik, sspitsyn --- .../test/runtime/7158988/FieldMonitor.java | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/hotspot/test/runtime/7158988/FieldMonitor.java b/hotspot/test/runtime/7158988/FieldMonitor.java index 5421f626278..9b16fc3d798 100644 --- a/hotspot/test/runtime/7158988/FieldMonitor.java +++ b/hotspot/test/runtime/7158988/FieldMonitor.java @@ -34,10 +34,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -56,6 +52,7 @@ import com.sun.jdi.event.EventQueue; import com.sun.jdi.event.EventSet; import com.sun.jdi.event.ModificationWatchpointEvent; import com.sun.jdi.event.VMDeathEvent; +import com.sun.jdi.event.VMStartEvent; import com.sun.jdi.event.VMDisconnectEvent; import com.sun.jdi.request.ClassPrepareRequest; import com.sun.jdi.request.EventRequest; @@ -71,24 +68,10 @@ public class FieldMonitor { public static void main(String[] args) throws IOException, InterruptedException { - StringBuffer sb = new StringBuffer(); - - for (int i=0; i < args.length; i++) { - sb.append(' '); - sb.append(args[i]); - } //VirtualMachine vm = launchTarget(sb.toString()); VirtualMachine vm = launchTarget(CLASS_NAME); System.out.println("Vm launched"); - // set watch field on already loaded classes - List referenceTypes = vm - .classesByName(CLASS_NAME); - for (ReferenceType refType : referenceTypes) { - addFieldWatch(vm, refType); - } - // watch for loaded classes - addClassWatch(vm); // process events EventQueue eventQueue = vm.eventQueue(); @@ -104,13 +87,15 @@ public class FieldMonitor { errThread.start(); outThread.start(); - - vm.resume(); boolean connected = true; + int watched = 0; while (connected) { EventSet eventSet = eventQueue.remove(); for (Event event : eventSet) { - if (event instanceof VMDeathEvent + System.out.println("FieldMonitor-main receives: "+event); + if (event instanceof VMStartEvent) { + addClassWatch(vm); + } else if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) { // exit connected = false; @@ -122,17 +107,17 @@ public class FieldMonitor { .referenceType(); addFieldWatch(vm, refType); } else if (event instanceof ModificationWatchpointEvent) { + watched++; System.out.println("sleep for 500 ms"); Thread.sleep(500); - System.out.println("resume..."); ModificationWatchpointEvent modEvent = (ModificationWatchpointEvent) event; System.out.println("old=" + modEvent.valueCurrent()); System.out.println("new=" + modEvent.valueToBe()); - System.out.println(); } } + System.out.println("resume..."); eventSet.resume(); } // Shutdown begins when event thread terminates @@ -142,6 +127,10 @@ public class FieldMonitor { } catch (InterruptedException exc) { // we don't interrupt } + + if (watched != 11) { // init + 10 modifications in TestPostFieldModification class + throw new Error("Expected to receive 11 times ModificationWatchpointEvent, but got "+watched); + } } /** From 4ab0b2732c2bb0113d559b9c7e2cdadb1e308eef Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Sat, 15 Feb 2014 13:03:38 -0500 Subject: [PATCH 150/265] 8027146: Class loading verification failure if GC occurs in Universe::flush_dependents_on Remove search in system dictionary and hacks, replace with verifying in CLD::_klasses list. Reviewed-by: dcubed, acorn --- .../share/vm/classfile/classLoaderData.cpp | 9 ++++++++- .../share/vm/classfile/classLoaderData.hpp | 3 ++- hotspot/src/share/vm/classfile/dictionary.cpp | 4 ++-- .../share/vm/classfile/systemDictionary.cpp | 19 +------------------ .../share/vm/classfile/systemDictionary.hpp | 6 +----- hotspot/src/share/vm/oops/arrayKlass.cpp | 6 +++--- hotspot/src/share/vm/oops/arrayKlass.hpp | 4 ++-- hotspot/src/share/vm/oops/instanceKlass.cpp | 15 ++++++--------- hotspot/src/share/vm/oops/instanceKlass.hpp | 2 +- hotspot/src/share/vm/oops/klass.cpp | 4 ++-- hotspot/src/share/vm/oops/klass.hpp | 6 +++--- hotspot/src/share/vm/oops/objArrayKlass.cpp | 6 +++--- hotspot/src/share/vm/oops/objArrayKlass.hpp | 4 ++-- 13 files changed, 36 insertions(+), 52 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 892ea92fb00..6b34e01506c 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -520,6 +520,13 @@ void ClassLoaderData::verify() { } } +bool ClassLoaderData::contains_klass(Klass* klass) { + for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + if (k == klass) return true; + } + return false; +} + // GC root of class loader data created. ClassLoaderData* ClassLoaderDataGraph::_head = NULL; diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index 9e76b50441f..3fcbb6b7d5c 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,6 +260,7 @@ class ClassLoaderData : public CHeapObj { jobject add_handle(Handle h); void add_class(Klass* k); void remove_class(Klass* k); + bool contains_klass(Klass* k); void record_dependency(Klass* to, TRAPS); void init_dependencies(TRAPS); diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index e308791caa7..9a2bb74f821 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -707,7 +707,7 @@ void Dictionary::verify() { loader_data->class_loader() == NULL || loader_data->class_loader()->is_instance(), "checking type of class_loader"); - e->verify(/*check_dictionary*/false); + e->verify(); probe->verify_protection_domain_set(); element_count++; } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index f5c5c017dcd..703443517fd 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2650,23 +2650,6 @@ void SystemDictionary::verify() { constraints()->verify(dictionary(), placeholders()); } - -void SystemDictionary::verify_obj_klass_present(Symbol* class_name, - ClassLoaderData* loader_data) { - GCMutexLocker mu(SystemDictionary_lock); - Symbol* name; - - Klass* probe = find_class(class_name, loader_data); - if (probe == NULL) { - probe = SystemDictionary::find_shared_class(class_name); - if (probe == NULL) { - name = find_placeholder(class_name, loader_data); - } - } - guarantee(probe != NULL || name != NULL, - "Loaded klasses should be in SystemDictionary"); -} - // utility function for class load event void SystemDictionary::post_class_load_event(const Ticks& start_time, instanceKlassHandle k, diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index b0e914ff9e4..88132f5209f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -375,10 +375,6 @@ public: static bool is_internal_format(Symbol* class_name); #endif - // Verify class is in dictionary - static void verify_obj_klass_present(Symbol* class_name, - ClassLoaderData* loader_data); - // Initialization static void initialize(TRAPS); diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 9e40206c253..fcb46b11f02 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -214,8 +214,8 @@ void ArrayKlass::oop_print_on(oop obj, outputStream* st) { // Verification -void ArrayKlass::verify_on(outputStream* st, bool check_dictionary) { - Klass::verify_on(st, check_dictionary); +void ArrayKlass::verify_on(outputStream* st) { + Klass::verify_on(st); if (component_mirror() != NULL) { guarantee(component_mirror()->klass() != NULL, "should have a class"); diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 4b06f1c0ed6..7b4ad2e9a99 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,7 +146,7 @@ class ArrayKlass: public Klass { void oop_print_on(oop obj, outputStream* st); // Verification - void verify_on(outputStream* st, bool check_dictionary); + void verify_on(outputStream* st); void oop_verify_on(oop obj, outputStream* st); }; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index a6ca58c42c1..ac9340a8777 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3180,7 +3180,7 @@ class VerifyFieldClosure: public OopClosure { virtual void do_oop(narrowOop* p) { VerifyFieldClosure::do_oop_work(p); } }; -void InstanceKlass::verify_on(outputStream* st, bool check_dictionary) { +void InstanceKlass::verify_on(outputStream* st) { #ifndef PRODUCT // Avoid redundant verifies, this really should be in product. if (_verify_count == Universe::verify_count()) return; @@ -3188,14 +3188,11 @@ void InstanceKlass::verify_on(outputStream* st, bool check_dictionary) { #endif // Verify Klass - Klass::verify_on(st, check_dictionary); + Klass::verify_on(st); - // Verify that klass is present in SystemDictionary if not already - // verifying the SystemDictionary. - if (is_loaded() && !is_anonymous() && check_dictionary) { - Symbol* h_name = name(); - SystemDictionary::verify_obj_klass_present(h_name, class_loader_data()); - } + // Verify that klass is present in ClassLoaderData + guarantee(class_loader_data()->contains_klass(this), + "this class isn't found in class loader data"); // Verify vtables if (is_linked()) { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index f503de6725a..db14be29a14 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1087,7 +1087,7 @@ public: const char* internal_name() const; // Verification - void verify_on(outputStream* st, bool check_dictionary); + void verify_on(outputStream* st); void oop_verify_on(oop obj, outputStream* st); }; diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index bf5dae0606d..adca246aaa9 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -638,7 +638,7 @@ void Klass::collect_statistics(KlassSizeStats *sz) const { // Verification -void Klass::verify_on(outputStream* st, bool check_dictionary) { +void Klass::verify_on(outputStream* st) { // This can be expensive, but it is worth checking that this klass is actually // in the CLD graph but not in production. diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 9855fdd3233..a31a2357355 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -695,8 +695,8 @@ class Klass : public Metadata { virtual const char* internal_name() const = 0; // Verification - virtual void verify_on(outputStream* st, bool check_dictionary); - void verify(bool check_dictionary = true) { verify_on(tty, check_dictionary); } + virtual void verify_on(outputStream* st); + void verify() { verify_on(tty); } #ifndef PRODUCT bool verify_vtable_index(int index); diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 7294ebe9adb..3316a8b27e6 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -674,8 +674,8 @@ const char* ObjArrayKlass::internal_name() const { // Verification -void ObjArrayKlass::verify_on(outputStream* st, bool check_dictionary) { - ArrayKlass::verify_on(st, check_dictionary); +void ObjArrayKlass::verify_on(outputStream* st) { + ArrayKlass::verify_on(st); guarantee(element_klass()->is_klass(), "should be klass"); guarantee(bottom_klass()->is_klass(), "should be klass"); Klass* bk = bottom_klass(); diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index af06fd42084..cfe31e86e61 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,7 +151,7 @@ class ObjArrayKlass : public ArrayKlass { const char* internal_name() const; // Verification - void verify_on(outputStream* st, bool check_dictionary); + void verify_on(outputStream* st); void oop_verify_on(oop obj, outputStream* st); }; From 10d4420b0815f86c68546b819423657658f19447 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Mon, 17 Feb 2014 09:51:37 +0100 Subject: [PATCH 151/265] 8033440: jmap reports unexpected used/free size of concurrent mark-sweep generation SA used the wrong type for the indexedFreeList in CompactibleFreeListSpace. Reviewed-by: coleenp, dsamersoff --- .../jvm/hotspot/memory/AdaptiveFreeList.java | 77 +++++++++++++++++++ .../memory/CompactibleFreeListSpace.java | 38 +++++---- .../sun/jvm/hotspot/memory/FreeList.java | 72 ----------------- .../concurrentMarkSweep/vmStructs_cms.hpp | 4 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 20 ++--- 5 files changed, 105 insertions(+), 106 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AdaptiveFreeList.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AdaptiveFreeList.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AdaptiveFreeList.java new file mode 100644 index 00000000000..19dca2610ce --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AdaptiveFreeList.java @@ -0,0 +1,77 @@ +/* + * @(#)AdaptiveFreeList.java + * + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.memory; + +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +public class AdaptiveFreeList extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("AdaptiveFreeList"); + sizeField = type.getCIntegerField("_size"); + countField = type.getCIntegerField("_count"); + headerSize = type.getSize(); + } + + // Fields + private static CIntegerField sizeField; + private static CIntegerField countField; + private static long headerSize; + + //Constructor + public AdaptiveFreeList(Address address) { + super(address); + } + + // Accessors + public long size() { + return sizeField.getValue(addr); + } + + public long count() { + return countField.getValue(addr); + } + + public static long sizeOf() { + return headerSize; + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java index 23cb0bcb7fb..ed26af725e0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,25 +24,29 @@ package sun.jvm.hotspot.memory; -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.*; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.debugger.Debugger; +import sun.jvm.hotspot.oops.ObjectHeap; +import sun.jvm.hotspot.oops.Oop; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; +import sun.jvm.hotspot.utilities.Assert; public class CompactibleFreeListSpace extends CompactibleSpace { private static AddressField collectorField; - - // for free size, three fields - // FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks - // FreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks - // LinearAllocBlock _smallLinearAllocBlock; // small linear alloc in TLAB private static AddressField indexedFreeListField; private static AddressField dictionaryField; private static long smallLinearAllocBlockFieldOffset; - private static long indexedFreeListSizeOf; private int heapWordSize; // 4 for 32bit, 8 for 64 bits private int IndexSetStart; // for small indexed list @@ -109,11 +113,11 @@ public class CompactibleFreeListSpace extends CompactibleSpace { // small chunks long size = 0; Address cur = addr.addOffsetTo( indexedFreeListField.getOffset() ); - cur = cur.addOffsetTo(IndexSetStart*FreeList.sizeOf()); + cur = cur.addOffsetTo(IndexSetStart*AdaptiveFreeList.sizeOf()); for (int i=IndexSetStart; i"); - sizeField = type.getCIntegerField("_size"); - countField = type.getCIntegerField("_count"); - headerSize = type.getSize(); - } - - // Fields - private static CIntegerField sizeField; - private static CIntegerField countField; - private static long headerSize; - - //Constructor - public FreeList(Address address) { - super(address); - } - - // Accessors - public long size() { - return sizeField.getValue(addr); - } - - public long count() { - return countField.getValue(addr); - } - - public static long sizeOf() { - return headerSize; - } -} diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index 1a46ed3f52d..2a0a563d5f4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ nonstatic_field(CompactibleFreeListSpace, _dictionary, AFLBinaryTreeDictionary*) \ - nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ + nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], AdaptiveFreeList) \ nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index c1191a0562c..b5cdb27b26f 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,7 +242,6 @@ typedef TwoOopHashtable KlassTwoOopHashtable; typedef Hashtable KlassHashtable; typedef HashtableEntry KlassHashtableEntry; typedef TwoOopHashtable SymbolTwoOopHashtable; -typedef BinaryTreeDictionary > MetablockTreeDictionary; //-------------------------------------------------------------------------------- // VM_STRUCTS @@ -1281,11 +1280,8 @@ typedef BinaryTreeDictionary > MetablockTreeDicti volatile_nonstatic_field(FreeChunk, _size, size_t) \ nonstatic_field(FreeChunk, _next, FreeChunk*) \ nonstatic_field(FreeChunk, _prev, FreeChunk*) \ - nonstatic_field(FreeList, _size, size_t) \ - nonstatic_field(FreeList, _size, size_t) \ - nonstatic_field(FreeList, _count, ssize_t) \ - nonstatic_field(FreeList, _count, ssize_t) \ - nonstatic_field(MetablockTreeDictionary, _total_size, size_t) + nonstatic_field(AdaptiveFreeList, _size, size_t) \ + nonstatic_field(AdaptiveFreeList, _count, ssize_t) //-------------------------------------------------------------------------------- @@ -2155,14 +2151,8 @@ typedef BinaryTreeDictionary > MetablockTreeDicti \ /* freelist */ \ declare_toplevel_type(FreeChunk*) \ - declare_toplevel_type(Metablock*) \ - declare_toplevel_type(FreeBlockDictionary*) \ - declare_toplevel_type(FreeList*) \ - declare_toplevel_type(FreeList) \ - declare_toplevel_type(FreeBlockDictionary*) \ - declare_toplevel_type(FreeList*) \ - declare_toplevel_type(FreeList) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_toplevel_type(AdaptiveFreeList*) \ + declare_toplevel_type(AdaptiveFreeList) //-------------------------------------------------------------------------------- From 43b711ea78c080bcc12eb50b68d212ef70d7a181 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Tue, 18 Feb 2014 09:15:40 +0100 Subject: [PATCH 152/265] 8034080: Remove the USDT1 dtrace code from Hotspot Reviewed-by: dholmes, coleenp --- hotspot/src/share/vm/code/nmethod.cpp | 33 - .../src/share/vm/compiler/compileBroker.cpp | 33 - .../concurrentMarkSweep/vmCMSOperations.cpp | 24 - .../shared/vmGCOperations.cpp | 15 - hotspot/src/share/vm/oops/instanceKlass.cpp | 46 - hotspot/src/share/vm/prims/jni.cpp | 1315 +---------------- hotspot/src/share/vm/prims/jvm.cpp | 33 +- hotspot/src/share/vm/prims/unsafe.cpp | 28 +- hotspot/src/share/vm/runtime/java.cpp | 8 - .../src/share/vm/runtime/objectMonitor.cpp | 34 - .../src/share/vm/runtime/sharedRuntime.cpp | 27 - hotspot/src/share/vm/runtime/synchronizer.cpp | 27 - hotspot/src/share/vm/runtime/thread.cpp | 33 - hotspot/src/share/vm/runtime/vmThread.cpp | 21 - .../share/vm/services/classLoadingService.cpp | 21 - .../src/share/vm/services/memoryManager.cpp | 23 - .../src/share/vm/services/runtimeService.cpp | 13 - hotspot/src/share/vm/utilities/dtrace.hpp | 143 +- ...usdt2_disabled.hpp => dtrace_disabled.hpp} | 10 +- 19 files changed, 86 insertions(+), 1801 deletions(-) rename hotspot/src/share/vm/utilities/{dtrace_usdt2_disabled.hpp => dtrace_disabled.hpp} (99%) diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 50ee61adfab..0dc8ed1f47a 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -50,27 +50,6 @@ // Only bother with this argument setup if dtrace is available -#ifndef USDT2 -HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load, - const char*, int, const char*, int, const char*, int, void*, size_t); - -HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload, - char*, int, char*, int, char*, int); - -#define DTRACE_METHOD_UNLOAD_PROBE(method) \ - { \ - Method* m = (method); \ - if (m != NULL) { \ - Symbol* klass_name = m->klass_name(); \ - Symbol* name = m->name(); \ - Symbol* signature = m->signature(); \ - HS_DTRACE_PROBE6(hotspot, compiled__method__unload, \ - klass_name->bytes(), klass_name->utf8_length(), \ - name->bytes(), name->utf8_length(), \ - signature->bytes(), signature->utf8_length()); \ - } \ - } -#else /* USDT2 */ #define DTRACE_METHOD_UNLOAD_PROBE(method) \ { \ Method* m = (method); \ @@ -84,7 +63,6 @@ HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload, (char *) signature->bytes(), signature->utf8_length()); \ } \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED @@ -1520,16 +1498,6 @@ bool nmethod::can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_ void nmethod::post_compiled_method_load_event() { Method* moop = method(); -#ifndef USDT2 - HS_DTRACE_PROBE8(hotspot, compiled__method__load, - moop->klass_name()->bytes(), - moop->klass_name()->utf8_length(), - moop->name()->bytes(), - moop->name()->utf8_length(), - moop->signature()->bytes(), - moop->signature()->utf8_length(), - insts_begin(), insts_size()); -#else /* USDT2 */ HOTSPOT_COMPILED_METHOD_LOAD( (char *) moop->klass_name()->bytes(), moop->klass_name()->utf8_length(), @@ -1538,7 +1506,6 @@ void nmethod::post_compiled_method_load_event() { (char *) moop->signature()->bytes(), moop->signature()->utf8_length(), insts_begin(), insts_size()); -#endif /* USDT2 */ if (JvmtiExport::should_post_compiled_method_load() || JvmtiExport::should_post_compiled_method_unload()) { diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 536bca7851a..51fff71d54b 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -60,38 +60,6 @@ // Only bother with this argument setup if dtrace is available -#ifndef USDT2 -HS_DTRACE_PROBE_DECL8(hotspot, method__compile__begin, - char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t); -HS_DTRACE_PROBE_DECL9(hotspot, method__compile__end, - char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t, bool); - -#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, comp_name) \ - { \ - Symbol* klass_name = (method)->klass_name(); \ - Symbol* name = (method)->name(); \ - Symbol* signature = (method)->signature(); \ - HS_DTRACE_PROBE8(hotspot, method__compile__begin, \ - comp_name, strlen(comp_name), \ - klass_name->bytes(), klass_name->utf8_length(), \ - name->bytes(), name->utf8_length(), \ - signature->bytes(), signature->utf8_length()); \ - } - -#define DTRACE_METHOD_COMPILE_END_PROBE(method, comp_name, success) \ - { \ - Symbol* klass_name = (method)->klass_name(); \ - Symbol* name = (method)->name(); \ - Symbol* signature = (method)->signature(); \ - HS_DTRACE_PROBE9(hotspot, method__compile__end, \ - comp_name, strlen(comp_name), \ - klass_name->bytes(), klass_name->utf8_length(), \ - name->bytes(), name->utf8_length(), \ - signature->bytes(), signature->utf8_length(), (success)); \ - } - -#else /* USDT2 */ - #define DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, comp_name) \ { \ Symbol* klass_name = (method)->klass_name(); \ @@ -115,7 +83,6 @@ HS_DTRACE_PROBE_DECL9(hotspot, method__compile__end, (char *) name->bytes(), name->utf8_length(), \ (char *) signature->bytes(), signature->utf8_length(), (success)); \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp index 8024d298f05..46c0650a772 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp @@ -35,14 +35,6 @@ #include "utilities/dtrace.hpp" -#ifndef USDT2 -HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__begin); -HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__end); - -HS_DTRACE_PROBE_DECL(hs_private, cms__remark__begin); -HS_DTRACE_PROBE_DECL(hs_private, cms__remark__end); -#endif /* !USDT2 */ - ////////////////////////////////////////////////////////// // Methods in abstract class VM_CMS_Operation ////////////////////////////////////////////////////////// @@ -138,11 +130,7 @@ void VM_CMS_Initial_Mark::doit() { // Nothing to do. return; } -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, cms__initmark__begin); -#else /* USDT2 */ HS_PRIVATE_CMS_INITMARK_BEGIN(); -#endif /* USDT2 */ _collector->_gc_timer_cm->register_gc_pause_start("Initial Mark"); @@ -158,11 +146,7 @@ void VM_CMS_Initial_Mark::doit() { _collector->_gc_timer_cm->register_gc_pause_end(); -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, cms__initmark__end); -#else /* USDT2 */ HS_PRIVATE_CMS_INITMARK_END(); -#endif /* USDT2 */ } ////////////////////////////////////////////////////////// @@ -173,11 +157,7 @@ void VM_CMS_Final_Remark::doit() { // Nothing to do. return; } -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, cms__remark__begin); -#else /* USDT2 */ HS_PRIVATE_CMS_REMARK_BEGIN(); -#endif /* USDT2 */ _collector->_gc_timer_cm->register_gc_pause_start("Final Mark"); @@ -194,11 +174,7 @@ void VM_CMS_Final_Remark::doit() { _collector->save_heap_summary(); _collector->_gc_timer_cm->register_gc_pause_end(); -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, cms__remark__end); -#else /* USDT2 */ HS_PRIVATE_CMS_REMARK_END(); -#endif /* USDT2 */ } // VM operation to invoke a concurrent collection of a diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index ca3c0f48310..9027b89c375 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -41,33 +41,18 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #endif // INCLUDE_ALL_GCS -#ifndef USDT2 -HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); -HS_DTRACE_PROBE_DECL(hotspot, gc__end); -#endif /* !USDT2 */ - // The same dtrace probe can't be inserted in two different files, so we // have to call it here, so it's only in one file. Can't create new probes // for the other file anymore. The dtrace probes have to remain stable. void VM_GC_Operation::notify_gc_begin(bool full) { -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, gc__begin, full); - HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#else /* USDT2 */ HOTSPOT_GC_BEGIN( full); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#endif /* USDT2 */ } void VM_GC_Operation::notify_gc_end() { -#ifndef USDT2 - HS_DTRACE_PROBE(hotspot, gc__end); - HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#else /* USDT2 */ HOTSPOT_GC_END(); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#endif /* USDT2 */ } void VM_GC_Operation::acquire_pending_list_lock() { diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index ac9340a8777..66b46725828 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -77,51 +77,6 @@ #ifdef DTRACE_ENABLED -#ifndef USDT2 - -HS_DTRACE_PROBE_DECL4(hotspot, class__initialization__required, - char*, intptr_t, oop, intptr_t); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__recursive, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__concurrent, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__erroneous, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__super__failed, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__clinit, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__error, - char*, intptr_t, oop, intptr_t, int); -HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, - char*, intptr_t, oop, intptr_t, int); - -#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \ - { \ - char* data = NULL; \ - int len = 0; \ - Symbol* name = (clss)->name(); \ - if (name != NULL) { \ - data = (char*)name->bytes(); \ - len = name->utf8_length(); \ - } \ - HS_DTRACE_PROBE4(hotspot, class__initialization__##type, \ - data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type); \ - } - -#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \ - { \ - char* data = NULL; \ - int len = 0; \ - Symbol* name = (clss)->name(); \ - if (name != NULL) { \ - data = (char*)name->bytes(); \ - len = name->utf8_length(); \ - } \ - HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \ - data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type, wait); \ - } -#else /* USDT2 */ #define HOTSPOT_CLASS_INITIALIZATION_required HOTSPOT_CLASS_INITIALIZATION_REQUIRED #define HOTSPOT_CLASS_INITIALIZATION_recursive HOTSPOT_CLASS_INITIALIZATION_RECURSIVE @@ -156,7 +111,6 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, HOTSPOT_CLASS_INITIALIZATION_##type( \ data, len, (clss)->class_loader(), thread_type, wait); \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index a24967eaa13..030393cd275 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -114,33 +114,6 @@ static jint CurrentVersion = JNI_VERSION_1_8; // return_value = 5; // return return_value; // JNI_END -#ifndef USDT2 -#define DT_RETURN_MARK_DECL(name, type) \ - HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \ - DTRACE_ONLY( \ - class DTraceReturnProbeMark_##name { \ - public: \ - const type& _ret_ref; \ - DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \ - ~DTraceReturnProbeMark_##name() { \ - HS_DTRACE_PROBE1(hotspot_jni, name##__return, _ret_ref); \ - } \ - } \ - ) -// Void functions are simpler since there's no return value -#define DT_VOID_RETURN_MARK_DECL(name) \ - HS_DTRACE_PROBE_DECL0(hotspot_jni, name##__return); \ - DTRACE_ONLY( \ - class DTraceReturnProbeMark_##name { \ - public: \ - ~DTraceReturnProbeMark_##name() { \ - HS_DTRACE_PROBE0(hotspot_jni, name##__return); \ - } \ - } \ - ) - -#else /* USDT2 */ - #define DT_RETURN_MARK_DECL(name, type, probe) \ DTRACE_ONLY( \ class DTraceReturnProbeMark_##name { \ @@ -162,7 +135,6 @@ static jint CurrentVersion = JNI_VERSION_1_8; } \ } \ ) -#endif /* USDT2 */ // Place these macros in the function to mark the return. Non-void // functions need the type and address of the return value. @@ -191,15 +163,9 @@ static jint CurrentVersion = JNI_VERSION_1_8; // Choose DT_RETURN_MARK macros based on the type: float/double -> void // (dtrace doesn't do FP yet) -#ifndef USDT2 -#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \ - FP_SELECT(TypeName, \ - DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) ) -#else /* USDT2 */ #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe) \ FP_SELECT(TypeName, \ DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) ) -#endif /* USDT2 */ #define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \ FP_SELECT(TypeName, \ DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) ) @@ -358,24 +324,16 @@ const int MAX_REASONABLE_LOCAL_CAPACITY = 4*K; // Implementation of JNI entries -#ifndef USDT2 -DT_RETURN_MARK_DECL(DefineClass, jclass); -#else /* USDT2 */ DT_RETURN_MARK_DECL(DefineClass, jclass , HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef, const jbyte *buf, jsize bufLen)) JNIWrapper("DefineClass"); -#ifndef USDT2 - DTRACE_PROBE5(hotspot_jni, DefineClass__entry, - env, name, loaderRef, buf, bufLen); -#else /* USDT2 */ HOTSPOT_JNI_DEFINECLASS_ENTRY( env, (char*) name, loaderRef, (char*) buf, bufLen); -#endif /* USDT2 */ + jclass cls = NULL; DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls); @@ -421,20 +379,13 @@ JNI_END static bool first_time_FindClass = true; -#ifndef USDT2 -DT_RETURN_MARK_DECL(FindClass, jclass); -#else /* USDT2 */ DT_RETURN_MARK_DECL(FindClass, jclass , HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) JNIWrapper("FindClass"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, FindClass__entry, env, name); -#else /* USDT2 */ + HOTSPOT_JNI_FINDCLASS_ENTRY(env, (char *)name); -#endif /* USDT2 */ jclass result = NULL; DT_RETURN_MARK(FindClass, jclass, (const jclass&)result); @@ -498,20 +449,14 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) return result; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID); -#else /* USDT2 */ DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID , HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) JNIWrapper("FromReflectedMethod"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, FromReflectedMethod__entry, env, method); -#else /* USDT2 */ + HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(env, method); -#endif /* USDT2 */ + jmethodID ret = NULL; DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret); @@ -538,20 +483,14 @@ JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(FromReflectedField, jfieldID); -#else /* USDT2 */ DT_RETURN_MARK_DECL(FromReflectedField, jfieldID , HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) JNIWrapper("FromReflectedField"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, FromReflectedField__entry, env, field); -#else /* USDT2 */ + HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(env, field); -#endif /* USDT2 */ + jfieldID ret = NULL; DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret); @@ -586,20 +525,15 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(ToReflectedMethod, jobject); -#else /* USDT2 */ + DT_RETURN_MARK_DECL(ToReflectedMethod, jobject , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic)) JNIWrapper("ToReflectedMethod"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, ToReflectedMethod__entry, env, cls, method_id, isStatic); -#else /* USDT2 */ + HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic); -#endif /* USDT2 */ + jobject ret = NULL; DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret); @@ -615,20 +549,14 @@ JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID meth return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetSuperclass, jclass); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetSuperclass, jclass , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) JNIWrapper("GetSuperclass"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetSuperclass__entry, env, sub); -#else /* USDT2 */ + HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub); -#endif /* USDT2 */ + jclass obj = NULL; DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj); @@ -657,21 +585,16 @@ JNI_END JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super)) JNIWrapper("IsSubclassOf"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, IsAssignableFrom__entry, env, sub, super); -#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super); -#endif /* USDT2 */ + oop sub_mirror = JNIHandles::resolve_non_null(sub); oop super_mirror = JNIHandles::resolve_non_null(super); if (java_lang_Class::is_primitive(sub_mirror) || java_lang_Class::is_primitive(super_mirror)) { jboolean ret = (sub_mirror == super_mirror); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret); -#endif /* USDT2 */ return ret; } Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror); @@ -679,28 +602,20 @@ JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass s assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom"); jboolean ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(Throw, jint); -#else /* USDT2 */ + DT_RETURN_MARK_DECL(Throw, jint , HOTSPOT_JNI_THROW_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj)) JNIWrapper("Throw"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, Throw__entry, env, obj); -#else /* USDT2 */ + HOTSPOT_JNI_THROW_ENTRY(env, obj); -#endif /* USDT2 */ + jint ret = JNI_OK; DT_RETURN_MARK(Throw, jint, (const jint&)ret); @@ -708,20 +623,15 @@ JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj)) ShouldNotReachHere(); JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(ThrowNew, jint); -#else /* USDT2 */ + DT_RETURN_MARK_DECL(ThrowNew, jint , HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message)) JNIWrapper("ThrowNew"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, ThrowNew__entry, env, clazz, message); -#else /* USDT2 */ + HOTSPOT_JNI_THROWNEW_ENTRY(env, clazz, (char *) message); -#endif /* USDT2 */ + jint ret = JNI_OK; DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret); @@ -750,30 +660,23 @@ static void jni_check_async_exceptions(JavaThread *thread) { JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env)) JNIWrapper("ExceptionOccurred"); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__entry, env); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(env); -#endif /* USDT2 */ + jni_check_async_exceptions(thread); oop exception = thread->pending_exception(); jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) JNIWrapper("ExceptionDescribe"); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionDescribe__entry, env); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(env); -#endif /* USDT2 */ + if (thread->has_pending_exception()) { Handle ex(thread, thread->pending_exception()); thread->clear_pending_exception(); @@ -809,21 +712,15 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) } } } -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ExceptionDescribe__return); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN(); -#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env)) JNIWrapper("ExceptionClear"); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionClear__entry, env); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(env); -#endif /* USDT2 */ // The jni code might be using this API to clear java thrown exception. // So just mark jvmti thread exception state as exception caught. @@ -832,21 +729,16 @@ JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env)) state->set_exception_caught(); } thread->clear_pending_exception(); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ExceptionClear__return); -#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN(); -#endif /* USDT2 */ JNI_END JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg)) JNIWrapper("FatalError"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, FatalError__entry, env, msg); -#else /* USDT2 */ + HOTSPOT_JNI_FATALERROR_ENTRY(env, (char *) msg); -#endif /* USDT2 */ + tty->print_cr("FATAL ERROR in native method: %s", msg); thread->print_stack(); os::abort(); // Dump core and abort @@ -855,18 +747,12 @@ JNI_END JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity)) JNIWrapper("PushLocalFrame"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, PushLocalFrame__entry, env, capacity); -#else /* USDT2 */ + HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(env, capacity); -#endif /* USDT2 */ + //%note jni_11 if (capacity < 0 || capacity > MAX_REASONABLE_LOCAL_CAPACITY) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR); -#else /* USDT2 */ HOTSPOT_JNI_PUSHLOCALFRAME_RETURN((uint32_t)JNI_ERR); -#endif /* USDT2 */ return JNI_ERR; } JNIHandleBlock* old_handles = thread->active_handles(); @@ -875,22 +761,16 @@ JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity)) new_handles->set_pop_frame_link(old_handles); thread->set_active_handles(new_handles); jint ret = JNI_OK; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result)) JNIWrapper("PopLocalFrame"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, PopLocalFrame__entry, env, result); -#else /* USDT2 */ + HOTSPOT_JNI_POPLOCALFRAME_ENTRY(env, result); -#endif /* USDT2 */ + //%note jni_11 Handle result_handle(thread, JNIHandles::resolve(result)); JNIHandleBlock* old_handles = thread->active_handles(); @@ -905,127 +785,91 @@ JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result)) JNIHandleBlock::release_block(old_handles, thread); // may block result = JNIHandles::make_local(thread, result_handle()); } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, PopLocalFrame__return, result); -#else /* USDT2 */ HOTSPOT_JNI_POPLOCALFRAME_RETURN(result); -#endif /* USDT2 */ return result; JNI_END JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("NewGlobalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, NewGlobalRef__entry, env, ref); -#else /* USDT2 */ + HOTSPOT_JNI_NEWGLOBALREF_ENTRY(env, ref); -#endif /* USDT2 */ + Handle ref_handle(thread, JNIHandles::resolve(ref)); jobject ret = JNIHandles::make_global(ref_handle); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, NewGlobalRef__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_NEWGLOBALREF_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END // Must be JNI_ENTRY (with HandleMark) JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("DeleteGlobalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, DeleteGlobalRef__entry, env, ref); -#else /* USDT2 */ + HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(env, ref); -#endif /* USDT2 */ + JNIHandles::destroy_global(ref); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, DeleteGlobalRef__return); -#else /* USDT2 */ + HOTSPOT_JNI_DELETEGLOBALREF_RETURN(); -#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj)) JNIWrapper("DeleteLocalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, DeleteLocalRef__entry, env, obj); -#else /* USDT2 */ + HOTSPOT_JNI_DELETELOCALREF_ENTRY(env, obj); -#endif /* USDT2 */ + JNIHandles::destroy_local(obj); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, DeleteLocalRef__return); -#else /* USDT2 */ + HOTSPOT_JNI_DELETELOCALREF_RETURN(); -#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2)) JNIWrapper("IsSameObject"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, IsSameObject__entry, env, r1, r2); -#else /* USDT2 */ + HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(env, r1, r2); -#endif /* USDT2 */ + oop a = JNIHandles::resolve(r1); oop b = JNIHandles::resolve(r2); jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, IsSameObject__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_ISSAMEOBJECT_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref)) JNIWrapper("NewLocalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, NewLocalRef__entry, env, ref); -#else /* USDT2 */ + HOTSPOT_JNI_NEWLOCALREF_ENTRY(env, ref); -#endif /* USDT2 */ + jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref)); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, NewLocalRef__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_NEWLOCALREF_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity)) JNIWrapper("EnsureLocalCapacity"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, EnsureLocalCapacity__entry, env, capacity); -#else /* USDT2 */ + HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(env, capacity); -#endif /* USDT2 */ + jint ret; if (capacity >= 0 && capacity <= MAX_REASONABLE_LOCAL_CAPACITY) { ret = JNI_OK; } else { ret = JNI_ERR; } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, EnsureLocalCapacity__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END // Return the Handle Type JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj)) JNIWrapper("GetObjectRefType"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetObjectRefType__entry, env, obj); -#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(env, obj); -#endif /* USDT2 */ + jobjectRefType ret; if (JNIHandles::is_local_handle(thread, obj) || JNIHandles::is_frame_handle(thread, obj)) @@ -1036,11 +880,8 @@ JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj)) ret = JNIWeakGlobalRefType; else ret = JNIInvalidRefType; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetObjectRefType__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN((void *) ret); -#endif /* USDT2 */ return ret; JNI_END @@ -1369,21 +1210,14 @@ static instanceOop alloc_object(jclass clazz, TRAPS) { return ih; } -#ifndef USDT2 -DT_RETURN_MARK_DECL(AllocObject, jobject); -#else /* USDT2 */ DT_RETURN_MARK_DECL(AllocObject, jobject , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz)) JNIWrapper("AllocObject"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, AllocObject__entry, env, clazz); -#else /* USDT2 */ HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz); -#endif /* USDT2 */ + jobject ret = NULL; DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret); @@ -1392,20 +1226,14 @@ JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz)) return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewObjectA, jobject); -#else /* USDT2 */ DT_RETURN_MARK_DECL(NewObjectA, jobject , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args)) JNIWrapper("NewObjectA"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, NewObjectA__entry, env, clazz, methodID); -#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID); -#endif /* USDT2 */ + jobject obj = NULL; DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj); @@ -1417,20 +1245,15 @@ JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, return obj; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewObjectV, jobject); -#else /* USDT2 */ + DT_RETURN_MARK_DECL(NewObjectV, jobject , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)) JNIWrapper("NewObjectV"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, NewObjectV__entry, env, clazz, methodID); -#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID); -#endif /* USDT2 */ + jobject obj = NULL; DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj); @@ -1442,20 +1265,15 @@ JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, return obj; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewObject, jobject); -#else /* USDT2 */ + DT_RETURN_MARK_DECL(NewObject, jobject , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)) JNIWrapper("NewObject"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, NewObject__entry, env, clazz, methodID); -#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID); -#endif /* USDT2 */ + jobject obj = NULL; DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj); @@ -1473,29 +1291,22 @@ JNI_END JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj)) JNIWrapper("GetObjectClass"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj); -#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj); -#endif /* USDT2 */ + Klass* k = JNIHandles::resolve_non_null(obj)->klass(); jclass ret = (jclass) JNIHandles::make_local(env, k->java_mirror()); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)) JNIWrapper("IsInstanceOf"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, IsInstanceOf__entry, env, obj, clazz); -#else /* USDT2 */ + HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz); -#endif /* USDT2 */ + jboolean ret = JNI_TRUE; if (obj != NULL) { ret = JNI_FALSE; @@ -1505,11 +1316,8 @@ JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass claz ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE; } } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, IsInstanceOf__return, ret); -#else /* USDT2 */ + HOTSPOT_JNI_ISINSTANCEOF_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END @@ -1569,17 +1377,9 @@ static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetMethodID"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, GetMethodID__entry, env, clazz, name, sig); -#else /* USDT2 */ HOTSPOT_JNI_GETMETHODID_ENTRY(env, clazz, (char *) name, (char *) sig); -#endif /* USDT2 */ jmethodID ret = get_method_id(env, clazz, name, sig, false, thread); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetMethodID__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETMETHODID_RETURN((uintptr_t) ret); -#endif /* USDT2 */ return ret; JNI_END @@ -1587,17 +1387,9 @@ JNI_END JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetStaticMethodID"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, GetStaticMethodID__entry, env, clazz, name, sig); -#else /* USDT2 */ HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(env, (char *) clazz, (char *) name, (char *)sig); -#endif /* USDT2 */ jmethodID ret = get_method_id(env, clazz, name, sig, true, thread); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStaticMethodID__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETSTATICMETHODID_RETURN((uintptr_t) ret); -#endif /* USDT2 */ return ret; JNI_END @@ -1607,82 +1399,6 @@ JNI_END // Calling Methods // -#ifndef USDT2 -#define DEFINE_CALLMETHOD(ResultType, Result, Tag) \ -\ - DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType);\ -\ -JNI_ENTRY(ResultType, \ - jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \ - JNIWrapper("Call" XSTR(Result) "Method"); \ -\ - DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID); \ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \ - (const ResultType&)ret);\ -\ - va_list args; \ - va_start(args, methodID); \ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ - va_end(args); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -\ -JNI_ENTRY(ResultType, \ - jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \ - JNIWrapper("Call" XSTR(Result) "MethodV"); \ -\ - DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID); \ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -\ -JNI_ENTRY(ResultType, \ - jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \ - JNIWrapper("Call" XSTR(Result) "MethodA"); \ - DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID); \ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherArray ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END - -// the runtime type of subword integral basic types is integer -DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN) -DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE) -DEFINE_CALLMETHOD(jchar, Char, T_CHAR) -DEFINE_CALLMETHOD(jshort, Short, T_SHORT) - -DEFINE_CALLMETHOD(jobject, Object, T_OBJECT) -DEFINE_CALLMETHOD(jint, Int, T_INT) -DEFINE_CALLMETHOD(jlong, Long, T_LONG) -DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT) -DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE) - -DT_VOID_RETURN_MARK_DECL(CallVoidMethod); -DT_VOID_RETURN_MARK_DECL(CallVoidMethodV); -DT_VOID_RETURN_MARK_DECL(CallVoidMethodA); - -#else /* USDT2 */ #define DEFINE_CALLMETHOD(ResultType, Result, Tag \ , EntryProbe, ReturnProbe) \ @@ -1849,15 +1565,10 @@ DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN()); DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN()); DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)) JNIWrapper("CallVoidMethod"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallVoidMethod__entry, env, obj, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(env, obj, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethod); va_list args; @@ -1871,11 +1582,7 @@ JNI_END JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) JNIWrapper("CallVoidMethodV"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallVoidMethodV__entry, env, obj, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(env, obj, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethodV); JavaValue jvalue(T_VOID); @@ -1886,11 +1593,7 @@ JNI_END JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) JNIWrapper("CallVoidMethodA"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallVoidMethodA__entry, env, obj, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(env, obj, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethodA); JavaValue jvalue(T_VOID); @@ -1899,80 +1602,6 @@ JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID JNI_END -#ifndef USDT2 -#define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag) \ -\ - DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType);\ -\ -JNI_ENTRY(ResultType, \ - jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \ - JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \ -\ - DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##Method__entry, env, obj, cls, methodID);\ - ResultType ret;\ - DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \ - (const ResultType&)ret);\ -\ - va_list args; \ - va_start(args, methodID); \ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ - va_end(args); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -JNI_ENTRY(ResultType, \ - jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \ - JNIWrapper("CallNonvitual" XSTR(Result) "#MethodV"); \ - DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodV__entry, env, obj, cls, methodID);\ - ResultType ret;\ - DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -JNI_ENTRY(ResultType, \ - jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \ - JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \ - DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodA__entry, env, obj, cls, methodID);\ - ResultType ret;\ - DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherArray ap(methodID, args); \ - jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END - -// the runtime type of subword integral basic types is integer -DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN) -DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE) -DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR) -DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT) - -DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT) -DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT) -DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG) -DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT) -DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE) - - -DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod); -DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV); -DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA); - -#else /* USDT2 */ #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \ , EntryProbe, ReturnProbe) \ @@ -2142,17 +1771,11 @@ DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN()); DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) JNIWrapper("CallNonvirtualVoidMethod"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethod__entry, - env, obj, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(env, obj, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod); va_list args; @@ -2167,13 +1790,8 @@ JNI_END JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) JNIWrapper("CallNonvirtualVoidMethodV"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodV__entry, - env, obj, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY( env, obj, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV); JavaValue jvalue(T_VOID); @@ -2184,13 +1802,8 @@ JNI_END JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) JNIWrapper("CallNonvirtualVoidMethodA"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodA__entry, - env, obj, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY( env, obj, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA); JavaValue jvalue(T_VOID); JNI_ArgumentPusherArray ap(methodID, args); @@ -2198,80 +1811,6 @@ JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass c JNI_END -#ifndef USDT2 -#define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag) \ -\ - DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType);\ - DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType);\ -\ -JNI_ENTRY(ResultType, \ - jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \ - JNIWrapper("CallStatic" XSTR(Result) "Method"); \ -\ - DTRACE_PROBE3(hotspot_jni, CallStatic##Result##Method__entry, env, cls, methodID);\ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \ - (const ResultType&)ret);\ -\ - va_list args; \ - va_start(args, methodID); \ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ - va_end(args); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -JNI_ENTRY(ResultType, \ - jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \ - JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \ - DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodV__entry, env, cls, methodID);\ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherVaArg ap(methodID, args); \ - jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END \ -\ -JNI_ENTRY(ResultType, \ - jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \ - JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \ - DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodA__entry, env, cls, methodID);\ - ResultType ret = 0;\ - DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \ - (const ResultType&)ret);\ -\ - JavaValue jvalue(Tag); \ - JNI_ArgumentPusherArray ap(methodID, args); \ - jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ - ret = jvalue.get_##ResultType(); \ - return ret;\ -JNI_END - -// the runtime type of subword integral basic types is integer -DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN) -DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE) -DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR) -DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT) - -DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT) -DEFINE_CALLSTATICMETHOD(jint, Int, T_INT) -DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG) -DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT) -DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE) - - -DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod); -DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV); -DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA); - -#else /* USDT2 */ #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \ , EntryProbe, ResultProbe) \ @@ -2445,15 +1984,10 @@ DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV , HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN()); DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA , HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)) JNIWrapper("CallStaticVoidMethod"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethod__entry, env, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(env, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethod); va_list args; @@ -2467,11 +2001,7 @@ JNI_END JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) JNIWrapper("CallStaticVoidMethodV"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodV__entry, env, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(env, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethodV); JavaValue jvalue(T_VOID); @@ -2482,11 +2012,7 @@ JNI_END JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) JNIWrapper("CallStaticVoidMethodA"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodA__entry, env, cls, methodID); -#else /* USDT2 */ HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(env, cls, (uintptr_t) methodID); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethodA); JavaValue jvalue(T_VOID); @@ -2500,21 +2026,13 @@ JNI_END // -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetFieldID, jfieldID); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetFieldID, jfieldID , HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetFieldID"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, GetFieldID__entry, env, clazz, name, sig); -#else /* USDT2 */ HOTSPOT_JNI_GETFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig); -#endif /* USDT2 */ jfieldID ret = 0; DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret); @@ -2546,11 +2064,7 @@ JNI_END JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) JNIWrapper("GetObjectField"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID); -#else /* USDT2 */ HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID); -#endif /* USDT2 */ oop o = JNIHandles::resolve_non_null(obj); Klass* k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); @@ -2580,50 +2094,11 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID } } #endif // INCLUDE_ALL_GCS -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END -#ifndef USDT2 -#define DEFINE_GETFIELD(Return,Fieldname,Result) \ -\ - DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return);\ -\ -JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \ - JNIWrapper("Get" XSTR(Result) "Field"); \ -\ - DTRACE_PROBE3(hotspot_jni, Get##Result##Field__entry, env, obj, fieldID);\ - Return ret = 0;\ - DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\ -\ - oop o = JNIHandles::resolve_non_null(obj); \ - Klass* k = o->klass(); \ - int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ - /* Keep JVMTI addition small and only check enabled flag here. */ \ - /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \ - /* and creates a ResetNoHandleMark. */ \ - if (JvmtiExport::should_post_field_access()) { \ - o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \ - } \ - ret = o->Fieldname##_field(offset); \ - return ret; \ -JNI_END - -DEFINE_GETFIELD(jboolean, bool, Boolean) -DEFINE_GETFIELD(jbyte, byte, Byte) -DEFINE_GETFIELD(jchar, char, Char) -DEFINE_GETFIELD(jshort, short, Short) -DEFINE_GETFIELD(jint, int, Int) -DEFINE_GETFIELD(jlong, long, Long) -DEFINE_GETFIELD(jfloat, float, Float) -DEFINE_GETFIELD(jdouble, double, Double) - -#else /* USDT2 */ #define DEFINE_GETFIELD(Return,Fieldname,Result \ , EntryProbe, ReturnProbe) \ @@ -2676,7 +2151,6 @@ DEFINE_GETFIELD(jfloat, float, Float DEFINE_GETFIELD(jdouble, double, Double , HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), HOTSPOT_JNI_GETDOUBLEFIELD_RETURN()) -#endif /* USDT2 */ address jni_GetBooleanField_addr() { return (address)jni_GetBooleanField; @@ -2705,11 +2179,7 @@ address jni_GetDoubleField_addr() { JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)) JNIWrapper("SetObjectField"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, SetObjectField__entry, env, obj, fieldID, value); -#else /* USDT2 */ HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value); -#endif /* USDT2 */ oop o = JNIHandles::resolve_non_null(obj); Klass* k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); @@ -2722,48 +2192,9 @@ JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fiel o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value); } o->obj_field_put(offset, JNIHandles::resolve(value)); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, SetObjectField__return); -#else /* USDT2 */ HOTSPOT_JNI_SETOBJECTFIELD_RETURN(); -#endif /* USDT2 */ JNI_END -#ifndef USDT2 -#define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType) \ -\ -JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \ - JNIWrapper("Set" XSTR(Result) "Field"); \ -\ - FP_SELECT_##Result( \ - DTRACE_PROBE4(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID, value), \ - DTRACE_PROBE3(hotspot_jni, Set##Result##Field__entry, env, obj, fieldID)); \ -\ - oop o = JNIHandles::resolve_non_null(obj); \ - Klass* k = o->klass(); \ - int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ - /* Keep JVMTI addition small and only check enabled flag here. */ \ - /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \ - /* and creates a ResetNoHandleMark. */ \ - if (JvmtiExport::should_post_field_modification()) { \ - jvalue field_value; \ - field_value.unionType = value; \ - o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ - } \ - o->Fieldname##_field_put(offset, value); \ - DTRACE_PROBE(hotspot_jni, Set##Result##Field__return);\ -JNI_END - -DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z) -DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b) -DEFINE_SETFIELD(jchar, char, Char, 'C', c) -DEFINE_SETFIELD(jshort, short, Short, 'S', s) -DEFINE_SETFIELD(jint, int, Int, 'I', i) -DEFINE_SETFIELD(jlong, long, Long, 'J', j) -DEFINE_SETFIELD(jfloat, float, Float, 'F', f) -DEFINE_SETFIELD(jdouble, double, Double, 'D', d) - -#else /* USDT2 */ #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \ , EntryProbe, ReturnProbe) \ @@ -2813,23 +2244,13 @@ DEFINE_SETFIELD(jfloat, float, Float, 'F', f DEFINE_SETFIELD(jdouble, double, Double, 'D', d , HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), HOTSPOT_JNI_SETDOUBLEFIELD_RETURN()) -#endif /* USDT2 */ -#ifndef USDT2 -DT_RETURN_MARK_DECL(ToReflectedField, jobject); -#else /* USDT2 */ DT_RETURN_MARK_DECL(ToReflectedField, jobject , HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic)) JNIWrapper("ToReflectedField"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, ToReflectedField__entry, - env, cls, fieldID, isStatic); -#else /* USDT2 */ HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(env, cls, (uintptr_t) fieldID, isStatic); -#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret); @@ -2859,21 +2280,13 @@ JNI_END // // Accessing Static Fields // -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID , HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetStaticFieldID"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, GetStaticFieldID__entry, env, clazz, name, sig); -#else /* USDT2 */ HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig); -#endif /* USDT2 */ jfieldID ret = NULL; DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret); @@ -2909,11 +2322,7 @@ JNI_END JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)) JNIWrapper("GetStaticObjectField"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetStaticObjectField__entry, env, clazz, fieldID); -#else /* USDT2 */ HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID); -#endif /* USDT2 */ #if INCLUDE_JNI_CHECK DEBUG_ONLY(Klass* param_k = jniCheck::validate_class(thread, clazz);) #endif // INCLUDE_JNI_CHECK @@ -2925,46 +2334,10 @@ JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); } jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset())); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStaticObjectField__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END -#ifndef USDT2 -#define DEFINE_GETSTATICFIELD(Return,Fieldname,Result) \ -\ - DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return);\ -\ -JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \ - JNIWrapper("GetStatic" XSTR(Result) "Field"); \ - DTRACE_PROBE3(hotspot_jni, GetStatic##Result##Field__entry, env, clazz, fieldID);\ - Return ret = 0;\ - DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \ - (const Return&)ret);\ - JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ - assert(id->is_static_field_id(), "invalid static field id"); \ - /* Keep JVMTI addition small and only check enabled flag here. */ \ - /* jni_GetField_probe() assumes that is okay to create handles. */ \ - if (JvmtiExport::should_post_field_access()) { \ - JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \ - } \ - ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \ - return ret;\ -JNI_END - -DEFINE_GETSTATICFIELD(jboolean, bool, Boolean) -DEFINE_GETSTATICFIELD(jbyte, byte, Byte) -DEFINE_GETSTATICFIELD(jchar, char, Char) -DEFINE_GETSTATICFIELD(jshort, short, Short) -DEFINE_GETSTATICFIELD(jint, int, Int) -DEFINE_GETSTATICFIELD(jlong, long, Long) -DEFINE_GETSTATICFIELD(jfloat, float, Float) -DEFINE_GETSTATICFIELD(jdouble, double, Double) - -#else /* USDT2 */ #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \ , EntryProbe, ReturnProbe) \ @@ -3006,15 +2379,10 @@ DEFINE_GETSTATICFIELD(jfloat, float, Float , HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() ) DEFINE_GETSTATICFIELD(jdouble, double, Double , HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() ) -#endif /* USDT2 */ JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)) JNIWrapper("SetStaticObjectField"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, SetStaticObjectField__entry, env, clazz, fieldID, value); -#else /* USDT2 */ HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value); -#endif /* USDT2 */ JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); assert(id->is_static_field_id(), "invalid static field id"); // Keep JVMTI addition small and only check enabled flag here. @@ -3025,46 +2393,10 @@ JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fie JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value); } id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value)); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, SetStaticObjectField__return); -#else /* USDT2 */ HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN(); -#endif /* USDT2 */ JNI_END -#ifndef USDT2 -#define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType) \ -\ -JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \ - JNIWrapper("SetStatic" XSTR(Result) "Field"); \ - FP_SELECT_##Result( \ - DTRACE_PROBE4(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID, value), \ - DTRACE_PROBE3(hotspot_jni, SetStatic##Result##Field__entry, env, clazz, fieldID)); \ -\ - JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ - assert(id->is_static_field_id(), "invalid static field id"); \ - /* Keep JVMTI addition small and only check enabled flag here. */ \ - /* jni_SetField_probe() assumes that is okay to create handles. */ \ - if (JvmtiExport::should_post_field_modification()) { \ - jvalue field_value; \ - field_value.unionType = value; \ - JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ - } \ - id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ - DTRACE_PROBE(hotspot_jni, SetStatic##Result##Field__return);\ -JNI_END - -DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z) -DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b) -DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c) -DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s) -DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i) -DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j) -DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f) -DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d) - -#else /* USDT2 */ #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \ , EntryProbe, ReturnProbe) \ @@ -3111,7 +2443,6 @@ DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d , HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN()) -#endif /* USDT2 */ // // String Operations @@ -3119,20 +2450,12 @@ DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d // Unicode Interface -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewString, jstring); -#else /* USDT2 */ DT_RETURN_MARK_DECL(NewString, jstring , HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len)) JNIWrapper("NewString"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, NewString__entry, env, unicodeChars, len); -#else /* USDT2 */ HOTSPOT_JNI_NEWSTRING_ENTRY(env, (uint16_t *) unicodeChars, len); -#endif /* USDT2 */ jstring ret = NULL; DT_RETURN_MARK(NewString, jstring, (const jstring&)ret); oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL); @@ -3143,21 +2466,13 @@ JNI_END JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string)) JNIWrapper("GetStringLength"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetStringLength__entry, env, string); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(env, string); -#endif /* USDT2 */ jsize ret = 0; oop s = JNIHandles::resolve_non_null(string); if (java_lang_String::value(s) != NULL) { ret = java_lang_String::length(s); } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END @@ -3165,11 +2480,7 @@ JNI_END JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringChars"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetStringChars__entry, env, string, isCopy); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(env, string, (uintptr_t *) isCopy); -#endif /* USDT2 */ jchar* buf = NULL; oop s = JNIHandles::resolve_non_null(string); typeArrayOop s_value = java_lang_String::value(s); @@ -3189,52 +2500,32 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( } } } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCHARS_RETURN(buf); -#endif /* USDT2 */ return buf; JNI_END JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringChars"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, ReleaseStringChars__entry, env, str, chars); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(env, str, (uint16_t *) chars); -#endif /* USDT2 */ //%note jni_6 if (chars != NULL) { // Since String objects are supposed to be immutable, don't copy any // new data back. A bad user will have to go after the char array. FreeHeap((void*) chars); } -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ReleaseStringChars__return); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN(); -#endif /* USDT2 */ JNI_END // UTF Interface -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewStringUTF, jstring); -#else /* USDT2 */ DT_RETURN_MARK_DECL(NewStringUTF, jstring , HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes)) JNIWrapper("NewStringUTF"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, NewStringUTF__entry, env, bytes); -#else /* USDT2 */ HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(env, (char *) bytes); -#endif /* USDT2 */ jstring ret; DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret); @@ -3246,32 +2537,20 @@ JNI_END JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string)) JNIWrapper("GetStringUTFLength"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetStringUTFLength__entry, env, string); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(env, string); -#endif /* USDT2 */ jsize ret = 0; oop java_string = JNIHandles::resolve_non_null(string); if (java_lang_String::value(java_string) != NULL) { ret = java_lang_String::utf8_length(java_string); } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringUTFChars"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(env, string, (uintptr_t *) isCopy); -#endif /* USDT2 */ char* result = NULL; oop java_string = JNIHandles::resolve_non_null(string); if (java_lang_String::value(java_string) != NULL) { @@ -3285,48 +2564,28 @@ JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboole } } } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(result); -#endif /* USDT2 */ return result; JNI_END JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars)) JNIWrapper("ReleaseStringUTFChars"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, ReleaseStringUTFChars__entry, env, str, chars); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(env, str, (char *) chars); -#endif /* USDT2 */ if (chars != NULL) { FreeHeap((char*) chars); } -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ReleaseStringUTFChars__return); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN(); -#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array)) JNIWrapper("GetArrayLength"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetArrayLength__entry, env, array); -#else /* USDT2 */ HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(env, array); -#endif /* USDT2 */ arrayOop a = arrayOop(JNIHandles::resolve_non_null(array)); assert(a->is_array(), "must be array"); jsize ret = a->length(); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetArrayLength__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETARRAYLENGTH_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END @@ -3335,20 +2594,12 @@ JNI_END // Object Array Operations // -#ifndef USDT2 -DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray); -#else /* USDT2 */ DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray , HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)) JNIWrapper("NewObjectArray"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, NewObjectArray__entry, env, length, elementClass, initialElement); -#else /* USDT2 */ HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(env, length, elementClass, initialElement); -#endif /* USDT2 */ jobjectArray ret = NULL; DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); KlassHandle ek(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass))); @@ -3366,20 +2617,12 @@ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass ele return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) JNIWrapper("GetObjectArrayElement"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetObjectArrayElement__entry, env, array, index); -#else /* USDT2 */ HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index); -#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); @@ -3393,20 +2636,12 @@ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, js } JNI_END -#ifndef USDT2 -DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement); -#else /* USDT2 */ DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) JNIWrapper("SetObjectArrayElement"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, SetObjectArrayElement__entry, env, array, index, value); -#else /* USDT2 */ HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(SetObjectArrayElement); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); @@ -3425,33 +2660,6 @@ JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize JNI_END -#ifndef USDT2 -#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \ -\ - DT_RETURN_MARK_DECL(New##Result##Array, Return); \ -\ -JNI_ENTRY(Return, \ - jni_New##Result##Array(JNIEnv *env, jsize len)) \ - JNIWrapper("New" XSTR(Result) "Array"); \ - DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\ - Return ret = NULL;\ - DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ -\ - oop obj= oopFactory::Allocator(len, CHECK_0); \ - ret = (Return) JNIHandles::make_local(env, obj); \ - return ret;\ -JNI_END - -DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean) -DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte) -DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short) -DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char) -DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int) -DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long) -DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float) -DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double) - -#else /* USDT2 */ #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \ ,EntryProbe,ReturnProbe) \ @@ -3495,7 +2703,6 @@ DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float, DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double, HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len), HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref)) -#endif /* USDT2 */ // Return an address which will fault if the caller writes to it. @@ -3513,47 +2720,6 @@ static char* get_bad_address() { } -#ifndef USDT2 -#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) \ -\ -JNI_QUICK_ENTRY(ElementType*, \ - jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \ - JNIWrapper("Get" XSTR(Result) "ArrayElements"); \ - DTRACE_PROBE3(hotspot_jni, Get##Result##ArrayElements__entry, env, array, isCopy);\ - /* allocate an chunk of memory in c land */ \ - typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - ElementType* result; \ - int len = a->length(); \ - if (len == 0) { \ - /* Empty array: legal but useless, can't return NULL. \ - * Return a pointer to something useless. \ - * Avoid asserts in typeArrayOop. */ \ - result = (ElementType*)get_bad_address(); \ - } else { \ - /* JNI Specification states return NULL on OOM */ \ - result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \ - if (result != NULL) { \ - /* copy the array to the c chunk */ \ - memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \ - if (isCopy) { \ - *isCopy = JNI_TRUE; \ - } \ - } \ - } \ - DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);\ - return result; \ -JNI_END - -DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool) -DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte) -DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short) -DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char) -DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int) -DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long) -DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) -DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) - -#else /* USDT2 */ #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \ , EntryProbe, ReturnProbe) \ @@ -3611,39 +2777,7 @@ DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double , HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result)) -#endif /* USDT2 */ -#ifndef USDT2 -#define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag) \ -\ -JNI_QUICK_ENTRY(void, \ - jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \ - ElementType *buf, jint mode)) \ - JNIWrapper("Release" XSTR(Result) "ArrayElements"); \ - DTRACE_PROBE4(hotspot_jni, Release##Result##ArrayElements__entry, env, array, buf, mode);\ - typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - int len = a->length(); \ - if (len != 0) { /* Empty array: nothing to free or copy. */ \ - if ((mode == 0) || (mode == JNI_COMMIT)) { \ - memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \ - } \ - if ((mode == 0) || (mode == JNI_ABORT)) { \ - FreeHeap(buf); \ - } \ - } \ - DTRACE_PROBE(hotspot_jni, Release##Result##ArrayElements__return);\ -JNI_END - -DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool) -DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte) -DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short) -DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char) -DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int) -DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long) -DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) -DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) - -#else /* USDT2 */ #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \ , EntryProbe, ReturnProbe);\ @@ -3690,41 +2824,7 @@ DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double , HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode), HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN()) -#endif /* USDT2 */ -#ifndef USDT2 -#define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ - DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion);\ -\ -JNI_ENTRY(void, \ -jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ - jsize len, ElementType *buf)) \ - JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \ - DTRACE_PROBE5(hotspot_jni, Get##Result##ArrayRegion__entry, env, array, start, len, buf);\ - DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \ - typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \ - THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ - } else { \ - if (len > 0) { \ - int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \ - memcpy((u_char*) buf, \ - (u_char*) src->Tag##_at_addr(start), \ - len << sc); \ - } \ - } \ -JNI_END - -DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool) -DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte) -DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short) -DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char) -DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int) -DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long) -DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) -DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) - -#else /* USDT2 */ #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ , EntryProbe, ReturnProbe); \ @@ -3774,41 +2874,7 @@ DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double , HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN()); -#endif /* USDT2 */ -#ifndef USDT2 -#define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ - DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion);\ -\ -JNI_ENTRY(void, \ -jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ - jsize len, const ElementType *buf)) \ - JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \ - DTRACE_PROBE5(hotspot_jni, Set##Result##ArrayRegion__entry, env, array, start, len, buf);\ - DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \ - typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \ - THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ - } else { \ - if (len > 0) { \ - int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \ - memcpy((u_char*) dst->Tag##_at_addr(start), \ - (u_char*) buf, \ - len << sc); \ - } \ - } \ -JNI_END - -DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool) -DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte) -DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short) -DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char) -DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int) -DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long) -DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) -DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) - -#else /* USDT2 */ #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ , EntryProbe, ReturnProbe); \ @@ -3858,7 +2924,6 @@ DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double , HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN()) -#endif /* USDT2 */ // @@ -3943,22 +3008,14 @@ static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, addr return true; } -#ifndef USDT2 -DT_RETURN_MARK_DECL(RegisterNatives, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(RegisterNatives, jint , HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods)) JNIWrapper("RegisterNatives"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, RegisterNatives__entry, env, clazz, methods, nMethods); -#else /* USDT2 */ HOTSPOT_JNI_REGISTERNATIVES_ENTRY(env, clazz, (void *) methods, nMethods); -#endif /* USDT2 */ jint ret = 0; DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret); @@ -3996,11 +3053,7 @@ JNI_END JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) JNIWrapper("UnregisterNatives"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, UnregisterNatives__entry, env, clazz); -#else /* USDT2 */ HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(env, clazz); -#endif /* USDT2 */ Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); //%note jni_2 if (k->oop_is_instance()) { @@ -4012,11 +3065,7 @@ JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) } } } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, UnregisterNatives__return, 0); -#else /* USDT2 */ HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(0); -#endif /* USDT2 */ return 0; JNI_END @@ -4024,19 +3073,11 @@ JNI_END // Monitor functions // -#ifndef USDT2 -DT_RETURN_MARK_DECL(MonitorEnter, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(MonitorEnter, jint , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj)) -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, MonitorEnter__entry, env, jobj); -#else /* USDT2 */ HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj); -#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret); @@ -4051,19 +3092,11 @@ JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj)) return ret; JNI_END -#ifndef USDT2 -DT_RETURN_MARK_DECL(MonitorExit, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(MonitorExit, jint , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref)); -#endif /* USDT2 */ JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj)) -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, MonitorExit__entry, env, jobj); -#else /* USDT2 */ HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj); -#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret); @@ -4083,20 +3116,12 @@ JNI_END // Extensions // -#ifndef USDT2 -DT_VOID_RETURN_MARK_DECL(GetStringRegion); -#else /* USDT2 */ DT_VOID_RETURN_MARK_DECL(GetStringRegion , HOTSPOT_JNI_GETSTRINGREGION_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf)) JNIWrapper("GetStringRegion"); -#ifndef USDT2 - DTRACE_PROBE5(hotspot_jni, GetStringRegion__entry, env, string, start, len, buf); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGREGION_ENTRY(env, string, start, len, buf); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(GetStringRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); @@ -4111,20 +3136,12 @@ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, js } JNI_END -#ifndef USDT2 -DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion); -#else /* USDT2 */ DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion , HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN()); -#endif /* USDT2 */ JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf)) JNIWrapper("GetStringUTFRegion"); -#ifndef USDT2 - DTRACE_PROBE5(hotspot_jni, GetStringUTFRegion__entry, env, string, start, len, buf); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(env, string, start, len, buf); -#endif /* USDT2 */ DT_VOID_RETURN_MARK(GetStringUTFRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); @@ -4150,11 +3167,7 @@ JNI_END JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)) JNIWrapper("GetPrimitiveArrayCritical"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetPrimitiveArrayCritical__entry, env, array, isCopy); -#else /* USDT2 */ HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(env, array, (uintptr_t *) isCopy); -#endif /* USDT2 */ GC_locker::lock_critical(thread); if (isCopy != NULL) { *isCopy = JNI_FALSE; @@ -4168,39 +3181,23 @@ JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboole type = TypeArrayKlass::cast(a->klass())->element_type(); } void* ret = arrayOop(a)->base(type); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetPrimitiveArrayCritical__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)) JNIWrapper("ReleasePrimitiveArrayCritical"); -#ifndef USDT2 - DTRACE_PROBE4(hotspot_jni, ReleasePrimitiveArrayCritical__entry, env, array, carray, mode); -#else /* USDT2 */ HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(env, array, carray, mode); -#endif /* USDT2 */ // The array, carray and mode arguments are ignored GC_locker::unlock_critical(thread); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ReleasePrimitiveArrayCritical__return); -#else /* USDT2 */ HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN(); -#endif /* USDT2 */ JNI_END JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringCritical"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy); -#endif /* USDT2 */ GC_locker::lock_critical(thread); if (isCopy != NULL) { *isCopy = JNI_FALSE; @@ -4215,80 +3212,44 @@ JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jbool } else { ret = (jchar*) s_value->base(T_CHAR); } -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret); -#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringCritical"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars); -#endif /* USDT2 */ // The str and chars arguments are ignored GC_locker::unlock_critical(thread); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return); -#else /* USDT2 */ HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN(); -#endif /* USDT2 */ JNI_END JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("jni_NewWeakGlobalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, NewWeakGlobalRef__entry, env, ref); -#else /* USDT2 */ HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref); -#endif /* USDT2 */ Handle ref_handle(thread, JNIHandles::resolve(ref)); jweak ret = JNIHandles::make_weak_global(ref_handle); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, NewWeakGlobalRef__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END // Must be JNI_ENTRY (with HandleMark) JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref)) JNIWrapper("jni_DeleteWeakGlobalRef"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, DeleteWeakGlobalRef__entry, env, ref); -#else /* USDT2 */ HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref); -#endif /* USDT2 */ JNIHandles::destroy_weak_global(ref); -#ifndef USDT2 - DTRACE_PROBE(hotspot_jni, DeleteWeakGlobalRef__return); -#else /* USDT2 */ HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN(); -#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env)) JNIWrapper("jni_ExceptionCheck"); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionCheck__entry, env); -#else /* USDT2 */ HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env); -#endif /* USDT2 */ jni_check_async_exceptions(thread); jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, ExceptionCheck__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(ret); -#endif /* USDT2 */ return ret; JNI_END @@ -4395,19 +3356,11 @@ extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, j JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_NewDirectByteBuffer"); -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity); -#else /* USDT2 */ HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(env, address, capacity); -#endif /* USDT2 */ if (!directBufferSupportInitializeEnded) { if (!initializeDirectBufferSupport(env, thread)) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL); -#else /* USDT2 */ HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(NULL); -#endif /* USDT2 */ return NULL; } } @@ -4418,20 +3371,12 @@ extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, j // takes int capacity jint cap = (jint) capacity; jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(ret); -#endif /* USDT2 */ return ret; } -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetDirectBufferAddress, void* , HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref)); -#endif /* USDT2 */ extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) { @@ -4439,11 +3384,7 @@ extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_GetDirectBufferAddress"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetDirectBufferAddress__entry, env, buf); -#else /* USDT2 */ HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(env, buf); -#endif /* USDT2 */ void* ret = NULL; DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); @@ -4461,12 +3402,8 @@ extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) return ret; } -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong , HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref)); -#endif /* USDT2 */ extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) { @@ -4474,11 +3411,7 @@ extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_GetDirectBufferCapacity"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetDirectBufferCapacity__entry, env, buf); -#else /* USDT2 */ HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(env, buf); -#endif /* USDT2 */ jlong ret = -1; DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); @@ -4505,16 +3438,8 @@ extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) JNI_LEAF(jint, jni_GetVersion(JNIEnv *env)) JNIWrapper("GetVersion"); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetVersion__entry, env); -#else /* USDT2 */ HOTSPOT_JNI_GETVERSION_ENTRY(env); -#endif /* USDT2 */ -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetVersion__return, CurrentVersion); -#else /* USDT2 */ HOTSPOT_JNI_GETVERSION_RETURN(CurrentVersion); -#endif /* USDT2 */ return CurrentVersion; JNI_END @@ -4522,17 +3447,9 @@ extern struct JavaVM_ main_vm; JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm)) JNIWrapper("jni_GetJavaVM"); -#ifndef USDT2 - DTRACE_PROBE2(hotspot_jni, GetJavaVM__entry, env, vm); -#else /* USDT2 */ HOTSPOT_JNI_GETJAVAVM_ENTRY(env, (void **) vm); -#endif /* USDT2 */ *vm = (JavaVM *)(&main_vm); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, GetJavaVM__return, JNI_OK); -#else /* USDT2 */ HOTSPOT_JNI_GETJAVAVM_RETURN(JNI_OK); -#endif /* USDT2 */ return JNI_OK; JNI_END @@ -4910,20 +3827,11 @@ struct JavaVM_ main_vm = {&jni_InvokeInterface}; #define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */ enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL }; -#ifndef USDT2 -HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*); -DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint , HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref)); -#endif /* USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, args_); -#else /* USDT2 */ HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(args_); -#endif /* USDT2 */ JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_; jint ret = JNI_ERR; DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret); @@ -5009,20 +3917,11 @@ void execute_internal_vm_tests() { #endif -#ifndef USDT2 -HS_DTRACE_PROBE_DECL3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); -DT_RETURN_MARK_DECL(CreateJavaVM, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(CreateJavaVM, jint , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref)); -#endif /* USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); -#else /* USDT2 */ HOTSPOT_JNI_CREATEJAVAVM_ENTRY((void **) vm, penv, args); -#endif /* USDT2 */ jint result = JNI_ERR; DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result); @@ -5144,50 +4043,30 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v return result; } -#ifndef USDT2 -HS_DTRACE_PROBE_DECL3(hotspot_jni, GetCreatedJavaVMs__entry, \ - JavaVM**, jsize, jsize*); -HS_DTRACE_PROBE_DECL1(hotspot_jni, GetCreatedJavaVMs__return, jint); -#endif /* !USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) { // See bug 4367188, the wrapper can sometimes cause VM crashes // JNIWrapper("GetCreatedJavaVMs"); -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot_jni, GetCreatedJavaVMs__entry, \ - vm_buf, bufLen, numVMs); -#else /* USDT2 */ + HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY((void **) vm_buf, bufLen, (uintptr_t *) numVMs); -#endif /* USDT2 */ + if (vm_created) { if (numVMs != NULL) *numVMs = 1; if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm); } else { if (numVMs != NULL) *numVMs = 0; } -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot_jni, GetCreatedJavaVMs__return, JNI_OK); -#else /* USDT2 */ HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(JNI_OK); -#endif /* USDT2 */ return JNI_OK; } extern "C" { -#ifndef USDT2 -DT_RETURN_MARK_DECL(DestroyJavaVM, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(DestroyJavaVM, jint , HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref)); -#endif /* USDT2 */ jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, DestroyJavaVM__entry, vm); -#else /* USDT2 */ HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(vm); -#endif /* USDT2 */ jint res = JNI_ERR; DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res); @@ -5339,58 +4218,34 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) { -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, AttachCurrentThread__entry, vm, penv, _args); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(vm, penv, _args); -#endif /* USDT2 */ if (!vm_created) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, JNI_ERR); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR); -#endif /* USDT2 */ return JNI_ERR; } JNIWrapper("AttachCurrentThread"); jint ret = attach_current_thread(vm, penv, _args, false); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(ret); -#endif /* USDT2 */ return ret; } jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__entry, vm); -#else /* USDT2 */ HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(vm); -#endif /* USDT2 */ VM_Exit::block_if_vm_exited(); JNIWrapper("DetachCurrentThread"); // If the thread has been deattacted the operations is a no-op if (ThreadLocalStorage::thread() == NULL) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); -#else /* USDT2 */ HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK); -#endif /* USDT2 */ return JNI_OK; } JavaThread* thread = JavaThread::current(); if (thread->has_last_Java_frame()) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_ERR); -#else /* USDT2 */ HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR); -#endif /* USDT2 */ // Can't detach a thread that's running java, that can't work. return JNI_ERR; } @@ -5411,27 +4266,15 @@ jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { thread->exit(false, JavaThread::jni_detach); delete thread; -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); -#else /* USDT2 */ HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK); -#endif /* USDT2 */ return JNI_OK; } -#ifndef USDT2 -DT_RETURN_MARK_DECL(GetEnv, jint); -#else /* USDT2 */ DT_RETURN_MARK_DECL(GetEnv, jint , HOTSPOT_JNI_GETENV_RETURN(_ret_ref)); -#endif /* USDT2 */ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, GetEnv__entry, vm, penv, version); -#else /* USDT2 */ HOTSPOT_JNI_GETENV_ENTRY(vm, penv, version); -#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(GetEnv, jint, (const jint&)ret); @@ -5485,27 +4328,15 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) { -#ifndef USDT2 - DTRACE_PROBE3(hotspot_jni, AttachCurrentThreadAsDaemon__entry, vm, penv, _args); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(vm, penv, _args); -#endif /* USDT2 */ if (!vm_created) { -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, JNI_ERR); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN((uint32_t) JNI_ERR); -#endif /* USDT2 */ return JNI_ERR; } JNIWrapper("AttachCurrentThreadAsDaemon"); jint ret = attach_current_thread(vm, penv, _args, true); -#ifndef USDT2 - DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, ret); -#else /* USDT2 */ HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(ret); -#endif /* USDT2 */ return ret; } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 2b4048ec0de..152f1d807ec 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -82,12 +82,6 @@ #include -#ifndef USDT2 -HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__begin, long long); -HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__end, int); -HS_DTRACE_PROBE_DECL0(hotspot, thread__yield); -#endif /* !USDT2 */ - /* NOTE about use of any ctor or function call that can trigger a safepoint/GC: such ctors and calls MUST NOT come between an oop declaration/init and its @@ -3008,11 +3002,8 @@ JVM_END JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) JVMWrapper("JVM_Yield"); if (os::dont_yield()) return; -#ifndef USDT2 - HS_DTRACE_PROBE0(hotspot, thread__yield); -#else /* USDT2 */ HOTSPOT_THREAD_YIELD(); -#endif /* USDT2 */ + // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // Critical for similar threading behaviour if (ConvertYieldToSleep) { @@ -3038,12 +3029,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) // And set new thread state to SLEEPING. JavaThreadSleepState jtss(thread); -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis); -#else /* USDT2 */ - HOTSPOT_THREAD_SLEEP_BEGIN( - millis); -#endif /* USDT2 */ + HOTSPOT_THREAD_SLEEP_BEGIN(millis); EventThreadSleep event; @@ -3071,12 +3057,8 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) event.set_time(millis); event.commit(); } -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1); -#else /* USDT2 */ - HOTSPOT_THREAD_SLEEP_END( - 1); -#endif /* USDT2 */ + HOTSPOT_THREAD_SLEEP_END(1); + // TODO-FIXME: THROW_MSG returns which means we will not call set_state() // to properly restore the thread state. That's likely wrong. THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); @@ -3088,12 +3070,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) event.set_time(millis); event.commit(); } -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0); -#else /* USDT2 */ - HOTSPOT_THREAD_SLEEP_END( - 0); -#endif /* USDT2 */ + HOTSPOT_THREAD_SLEEP_END(0); JVM_END JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 5a5d7c93c47..ec99c80f2af 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -44,11 +44,6 @@ * Implementation of class sun.misc.Unsafe */ -#ifndef USDT2 -HS_DTRACE_PROBE_DECL3(hotspot, thread__park__begin, uintptr_t, int, long long); -HS_DTRACE_PROBE_DECL1(hotspot, thread__park__end, uintptr_t); -HS_DTRACE_PROBE_DECL1(hotspot, thread__unpark, uintptr_t); -#endif /* !USDT2 */ #define MAX_OBJECT_SIZE \ ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \ @@ -1211,20 +1206,12 @@ UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) UnsafeWrapper("Unsafe_Park"); EventThreadPark event; -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot, thread__park__begin, thread->parker(), (int) isAbsolute, time); -#else /* USDT2 */ - HOTSPOT_THREAD_PARK_BEGIN( - (uintptr_t) thread->parker(), (int) isAbsolute, time); -#endif /* USDT2 */ + HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time); + JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, thread__park__end, thread->parker()); -#else /* USDT2 */ - HOTSPOT_THREAD_PARK_END( - (uintptr_t) thread->parker()); -#endif /* USDT2 */ + + HOTSPOT_THREAD_PARK_END((uintptr_t) thread->parker()); if (event.should_commit()) { oop obj = thread->current_park_blocker(); event.set_klass((obj != NULL) ? obj->klass() : NULL); @@ -1263,12 +1250,7 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) } } if (p != NULL) { -#ifndef USDT2 - HS_DTRACE_PROBE1(hotspot, thread__unpark, p); -#else /* USDT2 */ - HOTSPOT_THREAD_UNPARK( - (uintptr_t) p); -#endif /* USDT2 */ + HOTSPOT_THREAD_UNPARK((uintptr_t) p); p->unpark(); } UNSAFE_END diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 1c4087412cb..6c2d90daeaa 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -97,9 +97,6 @@ #include "opto/runtime.hpp" #endif -#ifndef USDT2 -HS_DTRACE_PROBE_DECL(hotspot, vm__shutdown); -#endif /* !USDT2 */ #ifndef PRODUCT @@ -603,13 +600,8 @@ void vm_exit(int code) { void notify_vm_shutdown() { // For now, just a dtrace probe. -#ifndef USDT2 - HS_DTRACE_PROBE(hotspot, vm__shutdown); - HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#else /* USDT2 */ HOTSPOT_VM_SHUTDOWN(); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); -#endif /* USDT2 */ } void vm_direct_exit(int code) { diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 9b86b43b636..dc9ef877fed 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -78,39 +78,6 @@ len = klassname->utf8_length(); \ } -#ifndef USDT2 - -HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify, - jlong, uintptr_t, char*, int); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll, - jlong, uintptr_t, char*, int); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__enter, - jlong, uintptr_t, char*, int); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__entered, - jlong, uintptr_t, char*, int); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit, - jlong, uintptr_t, char*, int); - -#define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ - { \ - if (DTraceMonitorProbes) { \ - DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ - HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid, \ - (monitor), bytes, len, (millis)); \ - } \ - } - -#define DTRACE_MONITOR_PROBE(probe, monitor, obj, thread) \ - { \ - if (DTraceMonitorProbes) { \ - DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ - HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid, \ - (uintptr_t)(monitor), bytes, len); \ - } \ - } - -#else /* USDT2 */ - #define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ { \ if (DTraceMonitorProbes) { \ @@ -135,7 +102,6 @@ HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit, } \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_MONITOR_WAIT_PROBE(obj, thread, millis, mon) {;} diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 698c8d2336a..0d36d9cf7c5 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -127,14 +127,6 @@ void SharedRuntime::generate_stubs() { #include -#ifndef USDT2 -HS_DTRACE_PROBE_DECL4(hotspot, object__alloc, Thread*, char*, int, size_t); -HS_DTRACE_PROBE_DECL7(hotspot, method__entry, int, - char*, int, char*, int, char*, int); -HS_DTRACE_PROBE_DECL7(hotspot, method__return, int, - char*, int, char*, int, char*, int); -#endif /* !USDT2 */ - // Implementation of SharedRuntime #ifndef PRODUCT @@ -969,14 +961,9 @@ int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o) { Klass* klass = o->klass(); int size = o->size(); Symbol* name = klass->name(); -#ifndef USDT2 - HS_DTRACE_PROBE4(hotspot, object__alloc, get_java_tid(thread), - name->bytes(), name->utf8_length(), size * HeapWordSize); -#else /* USDT2 */ HOTSPOT_OBJECT_ALLOC( get_java_tid(thread), (char *) name->bytes(), name->utf8_length(), size * HeapWordSize); -#endif /* USDT2 */ return 0; } @@ -986,18 +973,11 @@ JRT_LEAF(int, SharedRuntime::dtrace_method_entry( Symbol* kname = method->klass_name(); Symbol* name = method->name(); Symbol* sig = method->signature(); -#ifndef USDT2 - HS_DTRACE_PROBE7(hotspot, method__entry, get_java_tid(thread), - kname->bytes(), kname->utf8_length(), - name->bytes(), name->utf8_length(), - sig->bytes(), sig->utf8_length()); -#else /* USDT2 */ HOTSPOT_METHOD_ENTRY( get_java_tid(thread), (char *) kname->bytes(), kname->utf8_length(), (char *) name->bytes(), name->utf8_length(), (char *) sig->bytes(), sig->utf8_length()); -#endif /* USDT2 */ return 0; JRT_END @@ -1007,18 +987,11 @@ JRT_LEAF(int, SharedRuntime::dtrace_method_exit( Symbol* kname = method->klass_name(); Symbol* name = method->name(); Symbol* sig = method->signature(); -#ifndef USDT2 - HS_DTRACE_PROBE7(hotspot, method__return, get_java_tid(thread), - kname->bytes(), kname->utf8_length(), - name->bytes(), name->utf8_length(), - sig->bytes(), sig->utf8_length()); -#else /* USDT2 */ HOTSPOT_METHOD_RETURN( get_java_tid(thread), (char *) kname->bytes(), kname->utf8_length(), (char *) name->bytes(), name->utf8_length(), (char *) sig->bytes(), sig->utf8_length()); -#endif /* USDT2 */ return 0; JRT_END diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 39a44775edc..d51427a588d 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -84,32 +84,6 @@ len = klassname->utf8_length(); \ } -#ifndef USDT2 -HS_DTRACE_PROBE_DECL5(hotspot, monitor__wait, - jlong, uintptr_t, char*, int, long); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited, - jlong, uintptr_t, char*, int); - -#define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ - { \ - if (DTraceMonitorProbes) { \ - DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ - HS_DTRACE_PROBE5(hotspot, monitor__wait, jtid, \ - (monitor), bytes, len, (millis)); \ - } \ - } - -#define DTRACE_MONITOR_PROBE(probe, monitor, obj, thread) \ - { \ - if (DTraceMonitorProbes) { \ - DTRACE_MONITOR_PROBE_COMMON(obj, thread); \ - HS_DTRACE_PROBE4(hotspot, monitor__##probe, jtid, \ - (uintptr_t)(monitor), bytes, len); \ - } \ - } - -#else /* USDT2 */ - #define DTRACE_MONITOR_WAIT_PROBE(monitor, obj, thread, millis) \ { \ if (DTraceMonitorProbes) { \ @@ -130,7 +104,6 @@ HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited, } \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_MONITOR_WAIT_PROBE(obj, thread, millis, mon) {;} diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index e93b808ebba..ed2dfa67551 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -112,29 +112,6 @@ // Only bother with this argument setup if dtrace is available -#ifndef USDT2 -HS_DTRACE_PROBE_DECL(hotspot, vm__init__begin); -HS_DTRACE_PROBE_DECL(hotspot, vm__init__end); -HS_DTRACE_PROBE_DECL5(hotspot, thread__start, char*, intptr_t, - intptr_t, intptr_t, bool); -HS_DTRACE_PROBE_DECL5(hotspot, thread__stop, char*, intptr_t, - intptr_t, intptr_t, bool); - -#define DTRACE_THREAD_PROBE(probe, javathread) \ - { \ - ResourceMark rm(this); \ - int len = 0; \ - const char* name = (javathread)->get_thread_name(); \ - len = strlen(name); \ - HS_DTRACE_PROBE5(hotspot, thread__##probe, \ - name, len, \ - java_lang_Thread::thread_id((javathread)->threadObj()), \ - (javathread)->osthread()->thread_id(), \ - java_lang_Thread::is_daemon((javathread)->threadObj())); \ - } - -#else /* USDT2 */ - #define HOTSPOT_THREAD_PROBE_start HOTSPOT_THREAD_START #define HOTSPOT_THREAD_PROBE_stop HOTSPOT_THREAD_STOP @@ -151,8 +128,6 @@ HS_DTRACE_PROBE_DECL5(hotspot, thread__stop, char*, intptr_t, java_lang_Thread::is_daemon((javathread)->threadObj())); \ } -#endif /* USDT2 */ - #else // ndef DTRACE_ENABLED #define DTRACE_THREAD_PROBE(probe, javathread) @@ -3391,11 +3366,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { os::pause(); } -#ifndef USDT2 - HS_DTRACE_PROBE(hotspot, vm__init__begin); -#else /* USDT2 */ HOTSPOT_VM_INIT_BEGIN(); -#endif /* USDT2 */ // Record VM creation timing statistics TraceVmCreationTime create_vm_timer; @@ -3557,11 +3528,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // debug stuff, that does not work until all basic classes have been initialized. set_init_completed(); -#ifndef USDT2 - HS_DTRACE_PROBE(hotspot, vm__init__end); -#else /* USDT2 */ HOTSPOT_VM_INIT_END(); -#endif /* USDT2 */ // record VM initialization completion time #if INCLUDE_MANAGEMENT diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index bdb508208d4..98fb207c887 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -40,12 +40,6 @@ #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" -#ifndef USDT2 -HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int); -HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int); -HS_DTRACE_PROBE_DECL3(hotspot, vmops__end, char *, uintptr_t, int); -#endif /* !USDT2 */ - // Dummy VM operation to act as first element in our circular double-linked list class VM_Dummy: public VM_Operation { VMOp_Type type() const { return VMOp_Dummy; } @@ -154,14 +148,9 @@ void VMOperationQueue::drain_list_oops_do(OopClosure* f) { // High-level interface bool VMOperationQueue::add(VM_Operation *op) { -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot, vmops__request, op->name(), strlen(op->name()), - op->evaluation_mode()); -#else /* USDT2 */ HOTSPOT_VMOPS_REQUEST( (char *) op->name(), strlen(op->name()), op->evaluation_mode()); -#endif /* USDT2 */ // Encapsulates VM queue policy. Currently, that // only involves putting them on the right list @@ -358,14 +347,9 @@ void VMThread::evaluate_operation(VM_Operation* op) { { PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time()); -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot, vmops__begin, op->name(), strlen(op->name()), - op->evaluation_mode()); -#else /* USDT2 */ HOTSPOT_VMOPS_BEGIN( (char *) op->name(), strlen(op->name()), op->evaluation_mode()); -#endif /* USDT2 */ EventExecuteVMOperation event; @@ -383,14 +367,9 @@ void VMThread::evaluate_operation(VM_Operation* op) { event.commit(); } -#ifndef USDT2 - HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()), - op->evaluation_mode()); -#else /* USDT2 */ HOTSPOT_VMOPS_END( (char *) op->name(), strlen(op->name()), op->evaluation_mode()); -#endif /* USDT2 */ } // Last access of info in _cur_vm_operation! diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index aa2299fca6d..bdc33fdd2bb 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -37,26 +37,6 @@ // Only bother with this argument setup if dtrace is available -#ifndef USDT2 - -HS_DTRACE_PROBE_DECL4(hotspot, class__loaded, char*, int, oop, bool); -HS_DTRACE_PROBE_DECL4(hotspot, class__unloaded, char*, int, oop, bool); - -#define DTRACE_CLASSLOAD_PROBE(type, clss, shared) \ - { \ - char* data = NULL; \ - int len = 0; \ - Symbol* name = (clss)->name(); \ - if (name != NULL) { \ - data = (char*)name->bytes(); \ - len = name->utf8_length(); \ - } \ - HS_DTRACE_PROBE4(hotspot, class__##type, \ - data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), (shared)); \ - } - -#else /* USDT2 */ - #define HOTSPOT_CLASS_unloaded HOTSPOT_CLASS_UNLOADED #define HOTSPOT_CLASS_loaded HOTSPOT_CLASS_LOADED #define DTRACE_CLASSLOAD_PROBE(type, clss, shared) \ @@ -72,7 +52,6 @@ HS_DTRACE_PROBE_DECL4(hotspot, class__unloaded, char*, int, oop, bool); data, len, (clss)->class_loader(), (shared)); \ } -#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_CLASSLOAD_PROBE(type, clss, shared) diff --git a/hotspot/src/share/vm/services/memoryManager.cpp b/hotspot/src/share/vm/services/memoryManager.cpp index 0cfd05b78f5..f6ada6a8244 100644 --- a/hotspot/src/share/vm/services/memoryManager.cpp +++ b/hotspot/src/share/vm/services/memoryManager.cpp @@ -36,13 +36,6 @@ #include "services/gcNotifier.hpp" #include "utilities/dtrace.hpp" -#ifndef USDT2 -HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__begin, char*, int, char*, int, - size_t, size_t, size_t, size_t); -HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__end, char*, int, char*, int, - size_t, size_t, size_t, size_t); -#endif /* !USDT2 */ - MemoryManager::MemoryManager() { _num_pools = 0; (void)const_cast(_memory_mgr_obj = NULL); @@ -242,19 +235,11 @@ void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, MemoryPool* pool = MemoryService::get_memory_pool(i); MemoryUsage usage = pool->get_memory_usage(); _current_gc_stat->set_before_gc_usage(i, usage); -#ifndef USDT2 - HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, - name(), strlen(name()), - pool->name(), strlen(pool->name()), - usage.init_size(), usage.used(), - usage.committed(), usage.max_size()); -#else /* USDT2 */ HOTSPOT_MEM_POOL_GC_BEGIN( (char *) name(), strlen(name()), (char *) pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); -#endif /* USDT2 */ } } } @@ -280,19 +265,11 @@ void GCMemoryManager::gc_end(bool recordPostGCUsage, MemoryPool* pool = MemoryService::get_memory_pool(i); MemoryUsage usage = pool->get_memory_usage(); -#ifndef USDT2 - HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end, - name(), strlen(name()), - pool->name(), strlen(pool->name()), - usage.init_size(), usage.used(), - usage.committed(), usage.max_size()); -#else /* USDT2 */ HOTSPOT_MEM_POOL_GC_END( (char *) name(), strlen(name()), (char *) pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); -#endif /* USDT2 */ _current_gc_stat->set_after_gc_usage(i, usage); } diff --git a/hotspot/src/share/vm/services/runtimeService.cpp b/hotspot/src/share/vm/services/runtimeService.cpp index 379b8f3ff9e..5fdb9705a4d 100644 --- a/hotspot/src/share/vm/services/runtimeService.cpp +++ b/hotspot/src/share/vm/services/runtimeService.cpp @@ -31,11 +31,6 @@ #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" -#ifndef USDT2 -HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin); -HS_DTRACE_PROBE_DECL(hs_private, safepoint__end); -#endif /* !USDT2 */ - #if INCLUDE_MANAGEMENT TimeStamp RuntimeService::_app_timer; TimeStamp RuntimeService::_safepoint_timer; @@ -112,11 +107,7 @@ void RuntimeService::init() { } void RuntimeService::record_safepoint_begin() { -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, safepoint__begin); -#else /* USDT2 */ HS_PRIVATE_SAFEPOINT_BEGIN(); -#endif /* USDT2 */ // Print the time interval in which the app was executing if (PrintGCApplicationConcurrentTime && _app_timer.is_updated()) { @@ -143,11 +134,7 @@ void RuntimeService::record_safepoint_synchronized() { } void RuntimeService::record_safepoint_end() { -#ifndef USDT2 - HS_DTRACE_PROBE(hs_private, safepoint__end); -#else /* USDT2 */ HS_PRIVATE_SAFEPOINT_END(); -#endif /* USDT2 */ // Print the time interval for which the app was stopped // during the current safepoint operation. diff --git a/hotspot/src/share/vm/utilities/dtrace.hpp b/hotspot/src/share/vm/utilities/dtrace.hpp index 92d99de204a..e3612070354 100644 --- a/hotspot/src/share/vm/utilities/dtrace.hpp +++ b/hotspot/src/share/vm/utilities/dtrace.hpp @@ -37,7 +37,6 @@ // Work around dtrace tail call bug 6672627 until it is fixed in solaris 10. #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() \ do { volatile size_t dtrace_workaround_tail_call_bug = 1; } while (0) - #elif defined(LINUX) #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() #elif defined(__APPLE__) @@ -47,7 +46,6 @@ #error "dtrace enabled for unknown os" #endif /* defined(SOLARIS) */ -#define USDT2 1 #include "dtracefiles/hotspot.h" #include "dtracefiles/hotspot_jni.h" #include "dtracefiles/hs_private.h" @@ -59,147 +57,8 @@ #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() -#ifndef USDT2 - -#define DTRACE_PROBE(a,b) {;} -#define DTRACE_PROBE1(a,b,c) {;} -#define DTRACE_PROBE2(a,b,c,d) {;} -#define DTRACE_PROBE3(a,b,c,d,e) {;} -#define DTRACE_PROBE4(a,b,c,d,e,f) {;} -#define DTRACE_PROBE5(a,b,c,d,e,f,g) {;} -#define DTRACE_PROBE6(a,b,c,d,e,f,g,h) {;} -#define DTRACE_PROBE7(a,b,c,d,e,f,g,h,i) {;} -#define DTRACE_PROBE8(a,b,c,d,e,f,g,h,i,j) {;} -#define DTRACE_PROBE9(a,b,c,d,e,f,g,h,i,j,k) {;} -#define DTRACE_PROBE10(a,b,c,d,e,f,g,h,i,j,k,l) {;} - -#else /* USDT2 */ - -#include "dtrace_usdt2_disabled.hpp" -#endif /* USDT2 */ +#include "dtrace_disabled.hpp" #endif /* defined(DTRACE_ENABLED) */ -#ifndef USDT2 - -#define HS_DTRACE_PROBE_FN(provider,name)\ - __dtrace_##provider##___##name - -#ifdef SOLARIS -// Solaris dtrace needs actual extern function decls. -#define HS_DTRACE_PROBE_DECL_N(provider,name,args) \ - DTRACE_ONLY(extern "C" void HS_DTRACE_PROBE_FN(provider,name) args) -#define HS_DTRACE_PROBE_CDECL_N(provider,name,args) \ - DTRACE_ONLY(extern void HS_DTRACE_PROBE_FN(provider,name) args) -#else -// Systemtap dtrace compatible probes on GNU/Linux don't. -// If dtrace is disabled this macro becomes NULL -#define HS_DTRACE_PROBE_DECL_N(provider,name,args) -#define HS_DTRACE_PROBE_CDECL_N(provider,name,args) -#endif - -/* Dtrace probe declarations */ -#define HS_DTRACE_PROBE_DECL(provider,name) \ - HS_DTRACE_PROBE_DECL0(provider,name) -#define HS_DTRACE_PROBE_DECL0(provider,name)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(void)) -#define HS_DTRACE_PROBE_DECL1(provider,name,t0)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(uintptr_t)) -#define HS_DTRACE_PROBE_DECL2(provider,name,t0,t1)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL3(provider,name,t0,t1,t2)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(uintptr_t,uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL4(provider,name,t0,t1,t2,t3)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(uintptr_t,uintptr_t,uintptr_t,\ - uintptr_t)) -#define HS_DTRACE_PROBE_DECL5(provider,name,t0,t1,t2,t3,t4)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL6(provider,name,t0,t1,t2,t3,t4,t5)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL7(provider,name,t0,t1,t2,t3,t4,t5,t6)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL8(provider,name,t0,t1,t2,t3,t4,t5,t6,t7)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,\ - uintptr_t)) -#define HS_DTRACE_PROBE_DECL9(provider,name,t0,t1,t2,t3,t4,t5,t6,t7,t8)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,\ - uintptr_t,uintptr_t)) -#define HS_DTRACE_PROBE_DECL10(provider,name,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9)\ - HS_DTRACE_PROBE_DECL_N(provider,name,(\ - uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,uintptr_t,\ - uintptr_t,uintptr_t,uintptr_t)) - -/* Dtrace probe definitions */ -#if defined(SOLARIS) -// Solaris dtrace uses actual function calls. -#define HS_DTRACE_PROBE_N(provider,name, args) \ - DTRACE_ONLY(HS_DTRACE_PROBE_FN(provider,name) args) - -#define HS_DTRACE_PROBE(provider,name) HS_DTRACE_PROBE0(provider,name) -#define HS_DTRACE_PROBE0(provider,name)\ - HS_DTRACE_PROBE_N(provider,name,()) -#define HS_DTRACE_PROBE1(provider,name,a0)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0)) -#define HS_DTRACE_PROBE2(provider,name,a0,a1)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1)) -#define HS_DTRACE_PROBE3(provider,name,a0,a1,a2)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2)) -#define HS_DTRACE_PROBE4(provider,name,a0,a1,a2,a3)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3)) -#define HS_DTRACE_PROBE5(provider,name,a0,a1,a2,a3,a4)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4)) -#define HS_DTRACE_PROBE6(provider,name,a0,a1,a2,a3,a4,a5)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5)) -#define HS_DTRACE_PROBE7(provider,name,a0,a1,a2,a3,a4,a5,a6)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5,(uintptr_t)a6)) -#define HS_DTRACE_PROBE8(provider,name,a0,a1,a2,a3,a4,a5,a6,a7)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5,(uintptr_t)a6,(uintptr_t)a7)) -#define HS_DTRACE_PROBE9(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5,(uintptr_t)a6,(uintptr_t)a7,\ - (uintptr_t)a8)) -#define HS_DTRACE_PROBE10(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)\ - HS_DTRACE_PROBE_N(provider,name,((uintptr_t)a0,(uintptr_t)a1,(uintptr_t)a2,\ - (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5,(uintptr_t)a6,(uintptr_t)a7,\ - (uintptr_t)a8,(uintptr_t)a9)) -#else -// Systemtap dtrace compatible probes on GNU/Linux use direct macros. -// If dtrace is disabled this macro becomes NULL -#define HS_DTRACE_PROBE(provider,name) HS_DTRACE_PROBE0(provider,name) -#define HS_DTRACE_PROBE0(provider,name)\ - DTRACE_PROBE(provider,name) -#define HS_DTRACE_PROBE1(provider,name,a0)\ - DTRACE_PROBE1(provider,name,a0) -#define HS_DTRACE_PROBE2(provider,name,a0,a1)\ - DTRACE_PROBE2(provider,name,a0,a1) -#define HS_DTRACE_PROBE3(provider,name,a0,a1,a2)\ - DTRACE_PROBE3(provider,name,a0,a1,a2) -#define HS_DTRACE_PROBE4(provider,name,a0,a1,a2,a3)\ - DTRACE_PROBE4(provider,name,a0,a1,a2,a3) -#define HS_DTRACE_PROBE5(provider,name,a0,a1,a2,a3,a4)\ - DTRACE_PROBE5(provider,name,a0,a1,a2,a3,a4) -#define HS_DTRACE_PROBE6(provider,name,a0,a1,a2,a3,a4,a5)\ - DTRACE_PROBE6(provider,name,a0,a1,a2,a3,a4,a5) -#define HS_DTRACE_PROBE7(provider,name,a0,a1,a2,a3,a4,a5,a6)\ - DTRACE_PROBE7(provider,name,a0,a1,a2,a3,a4,a5,a6) -#define HS_DTRACE_PROBE8(provider,name,a0,a1,a2,a3,a4,a5,a6,a7)\ - DTRACE_PROBE8(provider,name,a0,a1,a2,a3,a4,a5,a6,a7) -#define HS_DTRACE_PROBE9(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8)\ - DTRACE_PROBE9(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8) -#define HS_DTRACE_PROBE10(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)\ - DTRACE_PROBE10(provider,name,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9) -#endif - -#endif /* !USDT2 */ - #endif // SHARE_VM_UTILITIES_DTRACE_HPP diff --git a/hotspot/src/share/vm/utilities/dtrace_usdt2_disabled.hpp b/hotspot/src/share/vm/utilities/dtrace_disabled.hpp similarity index 99% rename from hotspot/src/share/vm/utilities/dtrace_usdt2_disabled.hpp rename to hotspot/src/share/vm/utilities/dtrace_disabled.hpp index 5606bf62926..2906fe22e93 100644 --- a/hotspot/src/share/vm/utilities/dtrace_usdt2_disabled.hpp +++ b/hotspot/src/share/vm/utilities/dtrace_disabled.hpp @@ -32,8 +32,6 @@ */ #if !defined(DTRACE_ENABLED) -#ifdef USDT2 - /* hotspot provider probes */ #define HOTSPOT_CLASS_LOADED(arg0, arg1, arg2, arg3) #define HOTSPOT_CLASS_LOADED_ENABLED() 0 @@ -107,7 +105,7 @@ #define HOTSPOT_THREAD_PARK_BEGIN_ENABLED() 0 #define HOTSPOT_THREAD_PARK_END(arg0) #define HOTSPOT_THREAD_PARK_END_ENABLED() 0 -#define HOTSPOT_THREAD_UNPARK() +#define HOTSPOT_THREAD_UNPARK(arg0) #define HOTSPOT_THREAD_UNPARK_ENABLED() 0 #define HOTSPOT_VM_INIT_BEGIN() #define HOTSPOT_VM_INIT_BEGIN_ENABLED() 0 @@ -1086,12 +1084,8 @@ #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(arg0) #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN_ENABLED() 0 -#else /* USDT2 */ -#error This file should only be included for USDT2 -#endif /* USDT2 */ - #else /* !defined(DTRACE_ENABLED) */ #error This file should only be included when dtrace is not enabled -#end /* !defined(DTRACE_ENABLED) */ +#endif /* !defined(DTRACE_ENABLED) */ #endif // SHARE_VM_UTILITIES_DTRACE_USDT2_DISABLED_HPP From 95cdf53e755db37fc098edf31bbc81449a2de15f Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 18 Feb 2014 06:19:49 -0800 Subject: [PATCH 153/265] 8034249: need more workarounds for suspend equivalent condition issue Collect data at safepoint, do not rely on thread suspension Reviewed-by: dcubed, dholmes --- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 24 +++++++++++++-------- hotspot/src/share/vm/prims/jvmtiEnvBase.hpp | 20 +++++++++++------ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 6a197a84996..5aba54b6ca9 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -999,8 +999,9 @@ JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count GrowableArray *owned_monitors_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1, true); - uint32_t debug_bits = 0; - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == calling_thread) { err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); } else { // JVMTI get monitors info at safepoint. Do not require target thread to @@ -1044,8 +1045,9 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_i GrowableArray *owned_monitors_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1, true); - uint32_t debug_bits = 0; - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == calling_thread) { err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); } else { // JVMTI get owned monitors info at safepoint. Do not require target thread to @@ -1086,9 +1088,11 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_i jvmtiError JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) { jvmtiError err = JVMTI_ERROR_NONE; - uint32_t debug_bits = 0; JavaThread* calling_thread = JavaThread::current(); - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == calling_thread) { err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr); } else { // get contended monitor information at safepoint. @@ -1297,8 +1301,10 @@ JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jth jvmtiError JvmtiEnv::GetStackTrace(JavaThread* java_thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) { jvmtiError err = JVMTI_ERROR_NONE; - uint32_t debug_bits = 0; - if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { + + // It is only safe to perform the direct operation on the current + // thread. All other usage needs to use a vm-safepoint-op for safety. + if (java_thread == JavaThread::current()) { err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); } else { // JVMTI get stack trace at safepoint. Do not require target thread to diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index 0682118c88a..0f9495945ec 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -356,8 +356,12 @@ public: } VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; } void doit() { - ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, - _owned_monitors_list); + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + if (Threads::includes(_java_thread) && !_java_thread->is_exiting() + && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, + _owned_monitors_list); + } } jvmtiError result() { return _result; } }; @@ -439,9 +443,13 @@ public: jvmtiError result() { return _result; } VMOp_Type type() const { return VMOp_GetStackTrace; } void doit() { - _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, - _start_depth, _max_count, - _frame_buffer, _count_ptr); + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + if (Threads::includes(_java_thread) && !_java_thread->is_exiting() + && _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, + _start_depth, _max_count, + _frame_buffer, _count_ptr); + } } }; From db6974faf72e655af00af23efa763dd113d19c6b Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 18 Feb 2014 09:54:24 -0500 Subject: [PATCH 154/265] 8035132: [TESTBUG] test/runtime/lambda-features/InvokespecialInterface.java test has unrecognized option Add IgnoreUnrecognizedVMOptions for product mode run Reviewed-by: ctornqvi, dholmes --- .../test/runtime/lambda-features/InvokespecialInterface.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/test/runtime/lambda-features/InvokespecialInterface.java b/hotspot/test/runtime/lambda-features/InvokespecialInterface.java index 80c26186da2..c33dd56ef64 100644 --- a/hotspot/test/runtime/lambda-features/InvokespecialInterface.java +++ b/hotspot/test/runtime/lambda-features/InvokespecialInterface.java @@ -28,7 +28,7 @@ * @bug 8025937 * @bug 8033528 * @summary [JDK 8] Test invokespecial and invokeinterface with the same JVM_CONSTANT_InterfaceMethodref - * @run main/othervm -XX:+StressRewriter InvokespecialInterface + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+StressRewriter InvokespecialInterface */ import java.util.function.*; import java.util.*; From a9868648e69f7027c4c65cbc43372b52106081ae Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 19 Feb 2014 02:58:13 +0000 Subject: [PATCH 155/265] 7014526: "java -version" crash on sparc with some values of HeapBaseMinAddress Make default HeapBaseMinAddress the minimum that can be specified. Reviewed-by: minqi, kvn, tschatzl, dholmes --- hotspot/src/share/vm/runtime/arguments.cpp | 22 +++++++- .../CompressedClassPointers.java | 55 ++++++++++++------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 13dc79c2fe2..64d176b34bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1657,6 +1657,9 @@ julong Arguments::limit_by_allocatable_memory(julong limit) { return result; } +// Use static initialization to get the default before parsing +static const uintx DefaultHeapBaseMinAddress = HeapBaseMinAddress; + void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) { // Deprecated flag @@ -1688,6 +1691,23 @@ void Arguments::set_heap_size() { if (UseCompressedOops) { // Limit the heap size to the maximum possible when using compressed oops julong max_coop_heap = (julong)max_heap_for_compressed_oops(); + + // HeapBaseMinAddress can be greater than default but not less than. + if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) { + if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) { + if (PrintMiscellaneous && Verbose) { // matches compressed oops printing flags + jio_fprintf(defaultStream::error_stream(), + "HeapBaseMinAddress must be at least " UINTX_FORMAT + " (" UINTX_FORMAT "G) which is greater than value given " + UINTX_FORMAT "\n", + DefaultHeapBaseMinAddress, + DefaultHeapBaseMinAddress/G, + HeapBaseMinAddress); + } + FLAG_SET_ERGO(uintx, HeapBaseMinAddress, DefaultHeapBaseMinAddress); + } + } + if (HeapBaseMinAddress + MaxHeapSize < max_coop_heap) { // Heap should be above HeapBaseMinAddress to get zero based compressed oops // but it should be not less than default MaxHeapSize. diff --git a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java index 1892e6fd0b5..e801d5b87df 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java +++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,18 @@ public class CompressedClassPointers { output.shouldHaveExitValue(0); } + public static void heapBaseMinAddressTest() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:HeapBaseMinAddress=1m", + "-XX:+PrintMiscellaneous", + "-XX:+Verbose", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("HeapBaseMinAddress must be at least"); + output.shouldContain("HotSpot"); + output.shouldHaveExitValue(0); + } + public static void sharingTest() throws Exception { // Test small heaps ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( @@ -113,24 +125,25 @@ public class CompressedClassPointers { } } - public static void main(String[] args) throws Exception { - if (!Platform.is64bit()) { - // Can't test this on 32 bit, just pass - System.out.println("Skipping test on 32bit"); - return; - } - // Solaris 10 can't mmap compressed oops space without a base - if (Platform.isSolaris()) { - String name = System.getProperty("os.version"); - if (name.equals("5.10")) { - System.out.println("Skipping test on Solaris 10"); - return; - } - } - smallHeapTest(); - smallHeapTestWith3G(); - largeHeapTest(); - largePagesTest(); - sharingTest(); - } + public static void main(String[] args) throws Exception { + if (!Platform.is64bit()) { + // Can't test this on 32 bit, just pass + System.out.println("Skipping test on 32bit"); + return; + } + // Solaris 10 can't mmap compressed oops space without a base + if (Platform.isSolaris()) { + String name = System.getProperty("os.version"); + if (name.equals("5.10")) { + System.out.println("Skipping test on Solaris 10"); + return; + } + } + smallHeapTest(); + smallHeapTestWith3G(); + largeHeapTest(); + largePagesTest(); + heapBaseMinAddressTest(); + sharingTest(); + } } From eff08434da5b521d6a1faad9fb7a0d626722736c Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Wed, 19 Feb 2014 16:22:15 +0000 Subject: [PATCH 156/265] 6546236: Thread interrupt() of Thread.sleep() can be lost on Solaris due to race with signal handler Reviewed-by: dholmes, dcubed --- hotspot/src/os/bsd/vm/os_bsd.cpp | 129 +----------- hotspot/src/os/bsd/vm/os_bsd.hpp | 6 +- hotspot/src/os/bsd/vm/os_bsd.inline.hpp | 6 +- hotspot/src/os/linux/vm/os_linux.cpp | 133 +------------ hotspot/src/os/linux/vm/os_linux.hpp | 6 +- hotspot/src/os/linux/vm/os_linux.inline.hpp | 6 +- hotspot/src/os/posix/vm/os_posix.cpp | 132 ++++++++++++- hotspot/src/os/solaris/vm/os_solaris.cpp | 186 ------------------ .../src/os/solaris/vm/os_solaris.inline.hpp | 8 +- hotspot/src/os/windows/vm/os_windows.cpp | 20 +- hotspot/src/os/windows/vm/os_windows.hpp | 6 +- .../src/os/windows/vm/os_windows.inline.hpp | 6 +- hotspot/src/share/vm/runtime/os.hpp | 3 +- 13 files changed, 180 insertions(+), 467 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 5be87da64eb..02268213030 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -994,7 +994,7 @@ void os::Bsd::clock_init() { jlong os::javaTimeNanos() { - if (Bsd::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec tp; int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); assert(status == 0, "gettime error"); @@ -1010,7 +1010,7 @@ jlong os::javaTimeNanos() { } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (Bsd::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { info_ptr->max_value = ALL_64_BITS; // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past @@ -2559,85 +2559,6 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) { RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes)); } -// TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation. -// Solaris uses poll(), bsd uses park(). -// Poll() is likely a better choice, assuming that Thread.interrupt() -// generates a SIGUSRx signal. Note that SIGUSR1 can interfere with -// SIGSEGV, see 4355769. - -int os::sleep(Thread* thread, jlong millis, bool interruptible) { - assert(thread == Thread::current(), "thread consistency check"); - - ParkEvent * const slp = thread->_SleepEvent ; - slp->reset() ; - OrderAccess::fence() ; - - if (interruptible) { - jlong prevtime = javaTimeNanos(); - - for (;;) { - if (os::is_interrupted(thread, true)) { - return OS_INTRPT; - } - - jlong newtime = javaTimeNanos(); - - if (newtime - prevtime < 0) { - // time moving backwards, should only happen if no monotonic clock - // not a guarantee() because JVM should not abort on kernel/glibc bugs - assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); - } else { - millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; - } - - if(millis <= 0) { - return OS_OK; - } - - prevtime = newtime; - - { - assert(thread->is_Java_thread(), "sanity check"); - JavaThread *jt = (JavaThread *) thread; - ThreadBlockInVM tbivm(jt); - OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); - - jt->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or - // java_suspend_self() via check_and_wait_while_suspended() - - slp->park(millis); - - // were we externally suspended while we were waiting? - jt->check_and_wait_while_suspended(); - } - } - } else { - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); - jlong prevtime = javaTimeNanos(); - - for (;;) { - // It'd be nice to avoid the back-to-back javaTimeNanos() calls on - // the 1st iteration ... - jlong newtime = javaTimeNanos(); - - if (newtime - prevtime < 0) { - // time moving backwards, should only happen if no monotonic clock - // not a guarantee() because JVM should not abort on kernel/glibc bugs - assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); - } else { - millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; - } - - if(millis <= 0) break ; - - prevtime = newtime; - slp->park(millis); - } - return OS_OK ; - } -} - void os::naked_short_sleep(jlong ms) { struct timespec req; @@ -3033,50 +2954,6 @@ static void do_resume(OSThread* osthread) { guarantee(osthread->sr.is_running(), "Must be running!"); } -//////////////////////////////////////////////////////////////////////////////// -// interrupt support - -void os::interrupt(Thread* thread) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - if (!osthread->interrupted()) { - osthread->set_interrupted(true); - // More than one thread can get here with the same value of osthread, - // resulting in multiple notifications. We do, however, want the store - // to interrupted() to be visible to other threads before we execute unpark(). - OrderAccess::fence(); - ParkEvent * const slp = thread->_SleepEvent ; - if (slp != NULL) slp->unpark() ; - } - - // For JSR166. Unpark even if interrupt status already was set - if (thread->is_Java_thread()) - ((JavaThread*)thread)->parker()->unpark(); - - ParkEvent * ev = thread->_ParkEvent ; - if (ev != NULL) ev->unpark() ; - -} - -bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - bool interrupted = osthread->interrupted(); - - if (interrupted && clear_interrupted) { - osthread->set_interrupted(false); - // consider thread->_SleepEvent->reset() ... optional optimization - } - - return interrupted; -} - /////////////////////////////////////////////////////////////////////////////////// // signal handling (except suspend/resume) diff --git a/hotspot/src/os/bsd/vm/os_bsd.hpp b/hotspot/src/os/bsd/vm/os_bsd.hpp index a906a30e97f..5c85f863a85 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,10 +131,6 @@ class Bsd { // Real-time clock functions static void clock_init(void); - static inline bool supports_monotonic_clock() { - return _clock_gettime != NULL; - } - static int clock_gettime(clockid_t clock_id, struct timespec *tp) { return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; } diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp index cf8453332eb..61ae5b984e8 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -286,4 +286,8 @@ inline int os::set_sock_opt(int fd, int level, int optname, return ::setsockopt(fd, level, optname, optval, optlen); } +inline bool os::supports_monotonic_clock() { + return Bsd::_clock_gettime != NULL; +} + #endif // OS_BSD_VM_OS_BSD_INLINE_HPP diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 42f9471ea91..43907fbeba3 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1451,7 +1451,7 @@ void os::Linux::fast_thread_clock_init() { } jlong os::javaTimeNanos() { - if (Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec tp; int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp); assert(status == 0, "gettime error"); @@ -1467,7 +1467,7 @@ jlong os::javaTimeNanos() { } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { info_ptr->max_value = ALL_64_BITS; // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past @@ -3795,85 +3795,6 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) { return ::read(fd, buf, nBytes); } -// TODO-FIXME: reconcile Solaris' os::sleep with the linux variation. -// Solaris uses poll(), linux uses park(). -// Poll() is likely a better choice, assuming that Thread.interrupt() -// generates a SIGUSRx signal. Note that SIGUSR1 can interfere with -// SIGSEGV, see 4355769. - -int os::sleep(Thread* thread, jlong millis, bool interruptible) { - assert(thread == Thread::current(), "thread consistency check"); - - ParkEvent * const slp = thread->_SleepEvent ; - slp->reset() ; - OrderAccess::fence() ; - - if (interruptible) { - jlong prevtime = javaTimeNanos(); - - for (;;) { - if (os::is_interrupted(thread, true)) { - return OS_INTRPT; - } - - jlong newtime = javaTimeNanos(); - - if (newtime - prevtime < 0) { - // time moving backwards, should only happen if no monotonic clock - // not a guarantee() because JVM should not abort on kernel/glibc bugs - assert(!Linux::supports_monotonic_clock(), "time moving backwards"); - } else { - millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; - } - - if(millis <= 0) { - return OS_OK; - } - - prevtime = newtime; - - { - assert(thread->is_Java_thread(), "sanity check"); - JavaThread *jt = (JavaThread *) thread; - ThreadBlockInVM tbivm(jt); - OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); - - jt->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or - // java_suspend_self() via check_and_wait_while_suspended() - - slp->park(millis); - - // were we externally suspended while we were waiting? - jt->check_and_wait_while_suspended(); - } - } - } else { - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); - jlong prevtime = javaTimeNanos(); - - for (;;) { - // It'd be nice to avoid the back-to-back javaTimeNanos() calls on - // the 1st iteration ... - jlong newtime = javaTimeNanos(); - - if (newtime - prevtime < 0) { - // time moving backwards, should only happen if no monotonic clock - // not a guarantee() because JVM should not abort on kernel/glibc bugs - assert(!Linux::supports_monotonic_clock(), "time moving backwards"); - } else { - millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; - } - - if(millis <= 0) break ; - - prevtime = newtime; - slp->park(millis); - } - return OS_OK ; - } -} - // // Short sleep, direct OS call. // @@ -4226,50 +4147,6 @@ static void do_resume(OSThread* osthread) { guarantee(osthread->sr.is_running(), "Must be running!"); } -//////////////////////////////////////////////////////////////////////////////// -// interrupt support - -void os::interrupt(Thread* thread) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - if (!osthread->interrupted()) { - osthread->set_interrupted(true); - // More than one thread can get here with the same value of osthread, - // resulting in multiple notifications. We do, however, want the store - // to interrupted() to be visible to other threads before we execute unpark(). - OrderAccess::fence(); - ParkEvent * const slp = thread->_SleepEvent ; - if (slp != NULL) slp->unpark() ; - } - - // For JSR166. Unpark even if interrupt status already was set - if (thread->is_Java_thread()) - ((JavaThread*)thread)->parker()->unpark(); - - ParkEvent * ev = thread->_ParkEvent ; - if (ev != NULL) ev->unpark() ; - -} - -bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), - "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - bool interrupted = osthread->interrupted(); - - if (interrupted && clear_interrupted) { - osthread->set_interrupted(false); - // consider thread->_SleepEvent->reset() ... optional optimization - } - - return interrupted; -} - /////////////////////////////////////////////////////////////////////////////////// // signal handling (except suspend/resume) @@ -4787,7 +4664,7 @@ void os::init(void) { fatal(err_msg("pthread_condattr_init: %s", strerror(status))); } // Only set the clock if CLOCK_MONOTONIC is available - if (Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) { if (status == EINVAL) { warning("Unable to use monotonic clock with relative timed-waits" \ @@ -5618,7 +5495,7 @@ static struct timespec* compute_abstime(timespec* abstime, jlong millis) { seconds = 50000000; } - if (os::Linux::supports_monotonic_clock()) { + if (os::supports_monotonic_clock()) { struct timespec now; int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); assert_status(status == 0, status, "clock_gettime"); @@ -5835,7 +5712,7 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { assert (time > 0, "convertTime"); time_t max_secs = 0; - if (!os::Linux::supports_monotonic_clock() || isAbsolute) { + if (!os::supports_monotonic_clock() || isAbsolute) { struct timeval now; int status = gettimeofday(&now, NULL); assert(status == 0, "gettimeofday"); diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 5eed54f8c1e..95d06f1f4a9 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,10 +203,6 @@ class Linux { // fast POSIX clocks support static void fast_thread_clock_init(void); - static inline bool supports_monotonic_clock() { - return _clock_gettime != NULL; - } - static int clock_gettime(clockid_t clock_id, struct timespec *tp) { return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; } diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index 1afae5cc4e5..5f152d29726 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -288,4 +288,8 @@ inline int os::set_sock_opt(int fd, int level, int optname, return ::setsockopt(fd, level, optname, optval, optlen); } +inline bool os::supports_monotonic_clock() { + return Linux::_clock_gettime != NULL; +} + #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 63333172893..71fe4ec5302 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "prims/jvm.h" #include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/vmError.hpp" @@ -307,6 +308,135 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name, return agent_entry_name; } +int os::sleep(Thread* thread, jlong millis, bool interruptible) { + assert(thread == Thread::current(), "thread consistency check"); + + ParkEvent * const slp = thread->_SleepEvent ; + slp->reset() ; + OrderAccess::fence() ; + + if (interruptible) { + jlong prevtime = javaTimeNanos(); + + for (;;) { + if (os::is_interrupted(thread, true)) { + return OS_INTRPT; + } + + jlong newtime = javaTimeNanos(); + + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected in os::sleep(interruptible)"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + } + + if (millis <= 0) { + return OS_OK; + } + + prevtime = newtime; + + { + assert(thread->is_Java_thread(), "sanity check"); + JavaThread *jt = (JavaThread *) thread; + ThreadBlockInVM tbivm(jt); + OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); + + jt->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + slp->park(millis); + + // were we externally suspended while we were waiting? + jt->check_and_wait_while_suspended(); + } + } + } else { + OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + jlong prevtime = javaTimeNanos(); + + for (;;) { + // It'd be nice to avoid the back-to-back javaTimeNanos() calls on + // the 1st iteration ... + jlong newtime = javaTimeNanos(); + + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected on os::sleep(!interruptible)"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + } + + if (millis <= 0) break ; + + prevtime = newtime; + slp->park(millis); + } + return OS_OK ; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// interrupt support + +void os::interrupt(Thread* thread) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + if (!osthread->interrupted()) { + osthread->set_interrupted(true); + // More than one thread can get here with the same value of osthread, + // resulting in multiple notifications. We do, however, want the store + // to interrupted() to be visible to other threads before we execute unpark(). + OrderAccess::fence(); + ParkEvent * const slp = thread->_SleepEvent ; + if (slp != NULL) slp->unpark() ; + } + + // For JSR166. Unpark even if interrupt status already was set + if (thread->is_Java_thread()) + ((JavaThread*)thread)->parker()->unpark(); + + ParkEvent * ev = thread->_ParkEvent ; + if (ev != NULL) ev->unpark() ; + +} + +bool os::is_interrupted(Thread* thread, bool clear_interrupted) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + bool interrupted = osthread->interrupted(); + + // NOTE that since there is no "lock" around the interrupt and + // is_interrupted operations, there is the possibility that the + // interrupted flag (in osThread) will be "false" but that the + // low-level events will be in the signaled state. This is + // intentional. The effect of this is that Object.wait() and + // LockSupport.park() will appear to have a spurious wakeup, which + // is allowed and not harmful, and the possibility is so rare that + // it is not worth the added complexity to add yet another lock. + // For the sleep event an explicit reset is performed on entry + // to os::sleep, so there is no early return. It has also been + // recommended not to put the interrupted flag into the "event" + // structure because it hides the issue. + if (interrupted && clear_interrupted) { + osthread->set_interrupted(false); + // consider thread->_SleepEvent->reset() ... optional optimization + } + + return interrupted; +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 19ab10b4444..3c64286ce03 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -332,12 +332,6 @@ void os::Solaris::setup_interruptible(JavaThread* thread) { ThreadStateTransition::transition(thread, thread_state, _thread_blocked); } -// Version of setup_interruptible() for threads that are already in -// _thread_blocked. Used by os_sleep(). -void os::Solaris::setup_interruptible_already_blocked(JavaThread* thread) { - thread->frame_anchor()->make_walkable(thread); -} - JavaThread* os::Solaris::setup_interruptible() { JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread(); setup_interruptible(thread); @@ -3423,61 +3417,6 @@ bool os::can_execute_large_page_memory() { return true; } -static int os_sleep(jlong millis, bool interruptible) { - const jlong limit = INT_MAX; - jlong prevtime; - int res; - - while (millis > limit) { - if ((res = os_sleep(limit, interruptible)) != OS_OK) - return res; - millis -= limit; - } - - // Restart interrupted polls with new parameters until the proper delay - // has been completed. - - prevtime = getTimeMillis(); - - while (millis > 0) { - jlong newtime; - - if (!interruptible) { - // Following assert fails for os::yield_all: - // assert(!thread->is_Java_thread(), "must not be java thread"); - res = poll(NULL, 0, millis); - } else { - JavaThread *jt = JavaThread::current(); - - INTERRUPTIBLE_NORESTART_VM_ALWAYS(poll(NULL, 0, millis), res, jt, - os::Solaris::clear_interrupted); - } - - // INTERRUPTIBLE_NORESTART_VM_ALWAYS returns res == OS_INTRPT for - // thread.Interrupt. - - // See c/r 6751923. Poll can return 0 before time - // has elapsed if time is set via clock_settime (as NTP does). - // res == 0 if poll timed out (see man poll RETURN VALUES) - // using the logic below checks that we really did - // sleep at least "millis" if not we'll sleep again. - if( ( res == 0 ) || ((res == OS_ERR) && (errno == EINTR))) { - newtime = getTimeMillis(); - assert(newtime >= prevtime, "time moving backwards"); - /* Doing prevtime and newtime in microseconds doesn't help precision, - and trying to round up to avoid lost milliseconds can result in a - too-short delay. */ - millis -= newtime - prevtime; - if(millis <= 0) - return OS_OK; - prevtime = newtime; - } else - return res; - } - - return OS_OK; -} - // Read calls from inside the vm need to perform state transitions size_t os::read(int fd, void *buf, unsigned int nBytes) { INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); @@ -3487,69 +3426,6 @@ size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); } -int os::sleep(Thread* thread, jlong millis, bool interruptible) { - assert(thread == Thread::current(), "thread consistency check"); - - // TODO-FIXME: this should be removed. - // On Solaris machines (especially 2.5.1) we found that sometimes the VM gets into a live lock - // situation with a JavaThread being starved out of a lwp. The kernel doesn't seem to generate - // a SIGWAITING signal which would enable the threads library to create a new lwp for the starving - // thread. We suspect that because the Watcher thread keeps waking up at periodic intervals the kernel - // is fooled into believing that the system is making progress. In the code below we block the - // the watcher thread while safepoint is in progress so that it would not appear as though the - // system is making progress. - if (!Solaris::T2_libthread() && - thread->is_Watcher_thread() && SafepointSynchronize::is_synchronizing() && !Arguments::has_profile()) { - // We now try to acquire the threads lock. Since this lock is held by the VM thread during - // the entire safepoint, the watcher thread will line up here during the safepoint. - Threads_lock->lock_without_safepoint_check(); - Threads_lock->unlock(); - } - - if (thread->is_Java_thread()) { - // This is a JavaThread so we honor the _thread_blocked protocol - // even for sleeps of 0 milliseconds. This was originally done - // as a workaround for bug 4338139. However, now we also do it - // to honor the suspend-equivalent protocol. - - JavaThread *jt = (JavaThread *) thread; - ThreadBlockInVM tbivm(jt); - - jt->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or - // java_suspend_self() via check_and_wait_while_suspended() - - int ret_code; - if (millis <= 0) { - thr_yield(); - ret_code = 0; - } else { - // The original sleep() implementation did not create an - // OSThreadWaitState helper for sleeps of 0 milliseconds. - // I'm preserving that decision for now. - OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); - - ret_code = os_sleep(millis, interruptible); - } - - // were we externally suspended while we were waiting? - jt->check_and_wait_while_suspended(); - - return ret_code; - } - - // non-JavaThread from this point on: - - if (millis <= 0) { - thr_yield(); - return 0; - } - - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); - - return os_sleep(millis, interruptible); -} - void os::naked_short_sleep(jlong ms) { assert(ms < 1000, "Un-interruptable sleep, short time use only"); @@ -4192,68 +4068,6 @@ void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { errno = old_errno; } - -void os::interrupt(Thread* thread) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - int isInterrupted = osthread->interrupted(); - if (!isInterrupted) { - osthread->set_interrupted(true); - OrderAccess::fence(); - // os::sleep() is implemented with either poll (NULL,0,timeout) or - // by parking on _SleepEvent. If the former, thr_kill will unwedge - // the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper. - ParkEvent * const slp = thread->_SleepEvent ; - if (slp != NULL) slp->unpark() ; - } - - // For JSR166: unpark after setting status but before thr_kill -dl - if (thread->is_Java_thread()) { - ((JavaThread*)thread)->parker()->unpark(); - } - - // Handle interruptible wait() ... - ParkEvent * const ev = thread->_ParkEvent ; - if (ev != NULL) ev->unpark() ; - - // When events are used everywhere for os::sleep, then this thr_kill - // will only be needed if UseVMInterruptibleIO is true. - - if (!isInterrupted) { - int status = thr_kill(osthread->thread_id(), os::Solaris::SIGinterrupt()); - assert_status(status == 0, status, "thr_kill"); - - // Bump thread interruption counter - RuntimeService::record_thread_interrupt_signaled_count(); - } -} - - -bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); - - OSThread* osthread = thread->osthread(); - - bool res = osthread->interrupted(); - - // NOTE that since there is no "lock" around these two operations, - // there is the possibility that the interrupted flag will be - // "false" but that the interrupt event will be set. This is - // intentional. The effect of this is that Object.wait() will appear - // to have a spurious wakeup, which is not harmful, and the - // possibility is so rare that it is not worth the added complexity - // to add yet another lock. It has also been recommended not to put - // the interrupted flag into the os::Solaris::Event structure, - // because it hides the issue. - if (res && clear_interrupted) { - osthread->set_interrupted(false); - } - return res; -} - - void os::print_statistics() { } diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index 4155c0f5b1c..d7d53f223fc 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,4 +260,10 @@ inline int os::set_sock_opt(int fd, int level, int optname, const char *optval, socklen_t optlen) { return ::setsockopt(fd, level, optname, optval, optlen); } + +inline bool os::supports_monotonic_clock() { + // javaTimeNanos() is monotonic on Solaris, see getTimeNanos() comments + return true; +} + #endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 2fa8269ee5e..4cc42970ad0 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -628,8 +628,6 @@ void os::free_thread(OSThread* osthread) { delete osthread; } - -static int has_performance_count = 0; static jlong first_filetime; static jlong initial_performance_count; static jlong performance_frequency; @@ -645,7 +643,7 @@ jlong as_long(LARGE_INTEGER x) { jlong os::elapsed_counter() { LARGE_INTEGER count; - if (has_performance_count) { + if (win32::_has_performance_count) { QueryPerformanceCounter(&count); return as_long(count) - initial_performance_count; } else { @@ -657,7 +655,7 @@ jlong os::elapsed_counter() { jlong os::elapsed_frequency() { - if (has_performance_count) { + if (win32::_has_performance_count) { return performance_frequency; } else { // the FILETIME time is the number of 100-nanosecond intervals since January 1,1601. @@ -736,15 +734,15 @@ bool os::bind_to_processor(uint processor_id) { return false; } -static void initialize_performance_counter() { +void os::win32::initialize_performance_counter() { LARGE_INTEGER count; if (QueryPerformanceFrequency(&count)) { - has_performance_count = 1; + win32::_has_performance_count = 1; performance_frequency = as_long(count); QueryPerformanceCounter(&count); initial_performance_count = as_long(count); } else { - has_performance_count = 0; + win32::_has_performance_count = 0; FILETIME wt; GetSystemTimeAsFileTime(&wt); first_filetime = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime); @@ -839,7 +837,7 @@ jlong os::javaTimeMillis() { } jlong os::javaTimeNanos() { - if (!has_performance_count) { + if (!win32::_has_performance_count) { return javaTimeMillis() * NANOSECS_PER_MILLISEC; // the best we can do. } else { LARGE_INTEGER current_count; @@ -852,7 +850,7 @@ jlong os::javaTimeNanos() { } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { - if (!has_performance_count) { + if (!win32::_has_performance_count) { // javaTimeMillis() doesn't have much percision, // but it is not going to wrap -- so all 64 bits info_ptr->max_value = ALL_64_BITS; @@ -3682,6 +3680,8 @@ bool os::win32::_is_nt = false; bool os::win32::_is_windows_2003 = false; bool os::win32::_is_windows_server = false; +bool os::win32::_has_performance_count = 0; + void os::win32::initialize_system_info() { SYSTEM_INFO si; GetSystemInfo(&si); diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp index 67ed8a4af7c..f24ed28b6c1 100644 --- a/hotspot/src/os/windows/vm/os_windows.hpp +++ b/hotspot/src/os/windows/vm/os_windows.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ class win32 { static bool _is_nt; static bool _is_windows_2003; static bool _is_windows_server; + static bool _has_performance_count; static void print_windows_version(outputStream* st); @@ -60,6 +61,9 @@ class win32 { // load dll from Windows system directory or Windows directory static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen); + private: + static void initialize_performance_counter(); + public: // Generic interface: diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index 5303743aee4..a6d20d90b33 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,10 @@ inline int os::close(int fd) { return ::close(fd); } +inline bool os::supports_monotonic_clock() { + return win32::_has_performance_count; +} + #ifndef PRODUCT #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \ os::win32::call_test_func_with_wrapper(f) diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 0731663ddad..8854c327b8d 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,6 +161,7 @@ class os: AllStatic { static jlong javaTimeNanos(); static void javaTimeNanos_info(jvmtiTimerInfo *info_ptr); static void run_periodic_checks(); + static bool supports_monotonic_clock(); // Returns the elapsed time in seconds since the vm started. From 683ea742f26d16b56f2fb8dba1d1b1eacdc91547 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 19 Feb 2014 14:03:09 -0800 Subject: [PATCH 157/265] 8034797: AIX: Fix os::naked_short_sleep() in os_aix.cpp after 8028280 Imlements os::naked_short_sleep(jlong ms) on AIX Reviewed-by: dholmes, kvn --- hotspot/src/os/aix/vm/os_aix.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 2b0310d8410..ded1fe218f0 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -2894,9 +2894,21 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) { } } -int os::naked_sleep() { - // %% make the sleep time an integer flag. for now use 1 millisec. - return os::sleep(Thread::current(), 1, false); +void os::naked_short_sleep(jlong ms) { + struct timespec req; + + assert(ms < 1000, "Un-interruptable sleep, short time use only"); + req.tv_sec = 0; + if (ms > 0) { + req.tv_nsec = (ms % 1000) * 1000000; + } + else { + req.tv_nsec = 1; + } + + nanosleep(&req, NULL); + + return; } // Sleep forever; naked call to OS-specific sleep; use with CAUTION From 31ca5c712aff705b9d71ca2f38522d8a690a9f31 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 19 Feb 2014 15:05:19 -0800 Subject: [PATCH 158/265] 8035364: An extra space in the comments of constant pool entries Reviewed-by: ksrini --- .../com/sun/tools/javap/ConstantWriter.java | 18 +++++++++--------- langtools/test/tools/javap/T6868539.java | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java b/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java index fad08ac4856..f19ba36f609 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ public class ConstantWriter extends BasicWriter { public Integer visitClass(CONSTANT_Class_info info, Void p) { print("#" + info.name_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } @@ -76,7 +76,7 @@ public class ConstantWriter extends BasicWriter { public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) { print("#" + info.class_index + ".#" + info.name_and_type_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } @@ -93,14 +93,14 @@ public class ConstantWriter extends BasicWriter { public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { print("#" + info.class_index + ".#" + info.name_and_type_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) { print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } @@ -112,21 +112,21 @@ public class ConstantWriter extends BasicWriter { public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) { print("#" + info.name_index + ":#" + info.type_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) { print("#" + info.class_index + ".#" + info.name_and_type_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) { print("#" + info.reference_kind.tag + ":#" + info.reference_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } @@ -140,7 +140,7 @@ public class ConstantWriter extends BasicWriter { public Integer visitString(CONSTANT_String_info info, Void p) { print("#" + info.string_index); tab(); - println("// " + stringValue(info)); + println("// " + stringValue(info)); return 1; } diff --git a/langtools/test/tools/javap/T6868539.java b/langtools/test/tools/javap/T6868539.java index 3971ea0bffa..de0ebe08865 100644 --- a/langtools/test/tools/javap/T6868539.java +++ b/langtools/test/tools/javap/T6868539.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6868539 6868548 + * @bug 6868539 6868548 8035364 * @summary javap should use current names for constant pool entries, * remove spurious ';' from constant pool entries */ @@ -41,17 +41,17 @@ public class T6868539 void run() { String output = javap("T6868539"); verify(output, "Utf8 +java/lang/String"); // 1: Utf8 - // 2: currently unused + // 2: currently unused verify(output, "Integer +123456"); // 3: Integer verify(output, "Float +123456.0f"); // 4: Float verify(output, "Long +123456l"); // 5: Long verify(output, "Double +123456.0d"); // 6: Double - verify(output, "Class +#[0-9]+ +// + T6868539"); // 7: Class - verify(output, "String +#[0-9]+ +// + not found"); // 8: String + verify(output, "Class +#[0-9]+ +// +T6868539"); // 7: Class + verify(output, "String +#[0-9]+ +// +not found"); // 8: String verify(output, "Fieldref +#[0-9]+\\.#[0-9]+ +// +T6868539.errors:I"); // 9: Fieldref verify(output, "Methodref +#[0-9]+\\.#[0-9]+ +// +T6868539.run:\\(\\)V"); // 10: Methodref verify(output, "InterfaceMethodref +#[0-9]+\\.#[0-9]+ +// +java/lang/Runnable\\.run:\\(\\)V"); - // 11: InterfaceMethodref + // 11: InterfaceMethodref verify(output, "NameAndType +#[0-9]+:#[0-9]+ +// +run:\\(\\)V"); // 12: NameAndType if (errors > 0) throw new Error(errors + " found."); From b0422f5f5052bd3e266a2ead748cae32cb5cd8f4 Mon Sep 17 00:00:00 2001 From: Axel Siebenborn Date: Thu, 20 Feb 2014 10:48:57 +0100 Subject: [PATCH 159/265] 8035392: cppInterpreter: fix message of NPE Reviewed-by: kvn --- hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 7389d3afbf0..06261c804de 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -415,10 +415,10 @@ * On some architectures/platforms it should be possible to do this implicitly */ #undef CHECK_NULL -#define CHECK_NULL(obj_) \ - if ((obj_) == NULL) { \ - VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap); \ - } \ +#define CHECK_NULL(obj_) \ + if ((obj_) == NULL) { \ + VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), NULL, note_nullCheck_trap); \ + } \ VERIFY_OOP(obj_) #define VMdoubleConstZero() 0.0 From a5520f1c94d83d37da0ecd81976dd5a104a66917 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 20 Feb 2014 11:05:12 +0100 Subject: [PATCH 160/265] 8035394: PPC64: Make usage of intrinsic dsqrt depend on processor recognition Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/ppc.ad | 4 +++- hotspot/src/share/vm/opto/library_call.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index cb1d75dc08b..01d5ffb8314 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2076,6 +2076,8 @@ const bool Matcher::match_rule_supported(int opcode) { return false; switch (opcode) { + case Op_SqrtD: + return VM_Version::has_fsqrt(); case Op_CountLeadingZerosI: case Op_CountLeadingZerosL: case Op_CountTrailingZerosI: @@ -8740,7 +8742,7 @@ instruct negD_absD_reg(regD dst, regD src) %{ ins_pipe(pipe_class_default); %} -// VM_Version::has_sqrt() decides if this node will be used. +// VM_Version::has_fsqrt() decides if this node will be used. // Sqrt float double precision instruct sqrtD_reg(regD dst, regD src) %{ match(Set dst (SqrtD src)); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 3a2279ee568..465de355b67 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1937,7 +1937,7 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); // These intrinsics are supported on all hardware - case vmIntrinsics::_dsqrt: return Matcher::has_match_rule(Op_SqrtD) ? inline_math(id) : false; + case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false; case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; case vmIntrinsics::_dexp: return Matcher::has_match_rule(Op_ExpD) ? inline_exp() : From 05eda55e3cba1680a0f2707d665987beb0f087c6 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Thu, 20 Feb 2014 14:44:33 +0100 Subject: [PATCH 161/265] 8035423: AIX: Fix os::get_default_process_handle() in os_aix.cpp after 8031968 Reviewed-by: kvn --- hotspot/src/os/aix/vm/os_aix.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index ded1fe218f0..ba6b8d494c6 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1496,6 +1496,10 @@ void* os::dll_lookup(void* handle, const char* name) { return res; } +void* os::get_default_process_handle() { + return (void*)::dlopen(NULL, RTLD_LAZY); +} + void os::print_dll_info(outputStream *st) { st->print_cr("Dynamic libraries:"); LoadedLibraries::print(st); From 70c77b3470ba6cfccc52f17165ead786cce84f92 Mon Sep 17 00:00:00 2001 From: George Triantafillou Date: Thu, 20 Feb 2014 16:38:45 -0500 Subject: [PATCH 162/265] 8034898: [TESTBUG]: Zero failure project - tag all Runtime JTReg bugs that fail nightly Use @ignore to exclude failing tests Reviewed-by: coleenp, ctornqvi, mseledtsov --- hotspot/test/runtime/6925573/SortMethodsTest.java | 1 + hotspot/test/runtime/7107135/Test7107135.sh | 1 + .../runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java | 2 ++ hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java | 2 ++ .../test/runtime/SharedArchiveFile/DefaultUseWithClient.java | 2 ++ 5 files changed, 8 insertions(+) diff --git a/hotspot/test/runtime/6925573/SortMethodsTest.java b/hotspot/test/runtime/6925573/SortMethodsTest.java index 08b9c6c991a..ff60ab87df2 100644 --- a/hotspot/test/runtime/6925573/SortMethodsTest.java +++ b/hotspot/test/runtime/6925573/SortMethodsTest.java @@ -47,6 +47,7 @@ import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; /* + * @ignore 6959423 * @test SortMethodsTest * @bug 6925573 * @summary verify that class loading does not need quadratic time with regard to the number of class diff --git a/hotspot/test/runtime/7107135/Test7107135.sh b/hotspot/test/runtime/7107135/Test7107135.sh index 742c71c1ce2..f261aec3fc7 100644 --- a/hotspot/test/runtime/7107135/Test7107135.sh +++ b/hotspot/test/runtime/7107135/Test7107135.sh @@ -25,6 +25,7 @@ # ## +## @ignore 8025519 ## @test Test7107135.sh ## @bug 7107135 ## @bug 8021296 diff --git a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java index 0e9bb07762f..55eb104b050 100644 --- a/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java +++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java @@ -22,6 +22,7 @@ */ /* + * @ignore 8025642 * @test CdsDifferentObjectAlignment * @summary Testing CDS (class data sharing) using varying object alignment. * Using different object alignment for each dump/load pair. @@ -29,6 +30,7 @@ * is different from object alignment for creating a CDS file * should fail when loading. * @library /testlibrary + * @bug 8025642 */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java b/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java index 09189b9881a..05e469452ec 100644 --- a/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java +++ b/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java @@ -22,12 +22,14 @@ */ /* + * @ignore 8032222 * @test CdsWriteError * @summary Test how VM handles situation when it is impossible to write the * CDS archive. VM is expected to exit gracefully and display the * correct reason for the error. * @library /testlibrary * @run main CdsWriteError + * @bug 8032222 */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java b/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java index 9cbed20a04e..5883fab7ecc 100644 --- a/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java +++ b/hotspot/test/runtime/SharedArchiveFile/DefaultUseWithClient.java @@ -22,10 +22,12 @@ */ /* + * @ignore 8032224 * @test DefaultUseWithClient * @summary Test default behavior of sharing with -client * @library /testlibrary * @run main DefaultUseWithClient + * @bug 8032224 */ import com.oracle.java.testlibrary.*; From 4248787654112a59a744ad7b3b5f972a96fe6ba3 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 21 Feb 2014 10:01:20 +0100 Subject: [PATCH 163/265] 8035393: Use CLDClosure instead of CLDToOopClosure in frame::oops_interpreted_do Reviewed-by: tschatzl, coleenp --- .../vm/gc_implementation/parallelScavenge/psTasks.cpp | 4 ++-- hotspot/src/share/vm/memory/iterator.hpp | 7 ++++++- hotspot/src/share/vm/runtime/frame.cpp | 4 ++-- hotspot/src/share/vm/runtime/frame.hpp | 6 +++--- hotspot/src/share/vm/runtime/thread.cpp | 10 +++++----- hotspot/src/share/vm/runtime/thread.hpp | 10 +++++----- hotspot/src/share/vm/runtime/vmThread.cpp | 2 +- hotspot/src/share/vm/runtime/vmThread.hpp | 2 +- 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp index 6470281a992..ea0e627dc79 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp @@ -65,7 +65,7 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) { case threads: { ResourceMark rm; - CLDToOopClosure* cld_closure = NULL; // Not needed. All CLDs are already visited. + CLDClosure* cld_closure = NULL; // Not needed. All CLDs are already visited. Threads::oops_do(&roots_closure, cld_closure, NULL); } break; @@ -122,7 +122,7 @@ void ThreadRootsTask::do_it(GCTaskManager* manager, uint which) { PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which); PSScavengeRootsClosure roots_closure(pm); - CLDToOopClosure* roots_from_clds = NULL; // Not needed. All CLDs are already visited. + CLDClosure* roots_from_clds = NULL; // Not needed. All CLDs are already visited. CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true); if (_java_thread != NULL) diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp index dd98234d31e..33d10d69ef6 100644 --- a/hotspot/src/share/vm/memory/iterator.hpp +++ b/hotspot/src/share/vm/memory/iterator.hpp @@ -128,6 +128,11 @@ class KlassClosure : public Closure { virtual void do_klass(Klass* k) = 0; }; +class CLDClosure : public Closure { + public: + virtual void do_cld(ClassLoaderData* cld) = 0; +}; + class KlassToOopClosure : public KlassClosure { OopClosure* _oop_closure; public: @@ -135,7 +140,7 @@ class KlassToOopClosure : public KlassClosure { virtual void do_klass(Klass* k); }; -class CLDToOopClosure { +class CLDToOopClosure : public CLDClosure { OopClosure* _oop_closure; KlassToOopClosure _klass_closure; bool _must_claim_cld; diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 4bffc40833f..d47a9833ea0 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -895,7 +895,7 @@ oop* frame::interpreter_callee_receiver_addr(Symbol* signature) { } -void frame::oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f, +void frame::oops_interpreted_do(OopClosure* f, CLDClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache) { assert(is_interpreted_frame(), "Not an interpreted frame"); assert(map != NULL, "map must be set"); @@ -1146,7 +1146,7 @@ void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) { } -void frame::oops_do_internal(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) { +void frame::oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) { #ifndef PRODUCT // simulate GC crash here to dump java thread in error report if (CrashGCForDumpingJavaThread) { diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 78292c662ec..92b7a2607fa 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -416,19 +416,19 @@ class frame VALUE_OBJ_CLASS_SPEC { // 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, CLDToOopClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true); + void oops_interpreted_do(OopClosure* f, CLDClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true); private: void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f); // Iteration of oops - void oops_do_internal(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); + void oops_do_internal(OopClosure* f, CLDClosure* cld_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); int adjust_offset(Method* method, int index); // helper for above fn public: // Memory management - void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); } + void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); } void nmethods_do(CodeBlobClosure* cf); // RedefineClasses support for finding live interpreted methods on the stack diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index e93b808ebba..169cf32cc60 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -826,7 +826,7 @@ bool Thread::claim_oops_do_par_case(int strong_roots_parity) { return false; } -void Thread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void Thread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { active_handles()->oops_do(f); // Do oop for ThreadShadow f->do_oop((oop*)&_pending_exception); @@ -2722,7 +2722,7 @@ public: } }; -void JavaThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void JavaThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { // Verify that the deferred card marks have been flushed. assert(deferred_card_mark().is_empty(), "Should be empty during GC"); @@ -3245,7 +3245,7 @@ CompilerThread::CompilerThread(CompileQueue* queue, CompilerCounters* counters) #endif } -void CompilerThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void CompilerThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { JavaThread::oops_do(f, cld_f, cf); if (_scanned_nmethod != NULL && cf != NULL) { // Safepoints can occur when the sweeper is scanning an nmethod so @@ -4141,14 +4141,14 @@ bool Threads::includes(JavaThread* p) { // uses the Threads_lock to guarantee this property. It also makes sure that // all threads gets blocked when exiting or starting). -void Threads::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void Threads::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { p->oops_do(f, cld_f, cf); } VMThread::vm_thread()->oops_do(f, cld_f, cf); } -void Threads::possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void Threads::possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { // Introduce a mechanism allowing parallel threads to claim threads as // root groups. Overhead should be small enough to use all the time, // even in sequential code. diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index ec862167dc5..cd89dfa5075 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -487,7 +487,7 @@ class Thread: public ThreadShadow { // Apply "cld_f->do_cld" to CLDs that are otherwise not kept alive. // Used by JavaThread::oops_do. // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames - virtual void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + virtual void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); // Handles the parallel case for the method below. private: @@ -1424,7 +1424,7 @@ class JavaThread: public Thread { void frames_do(void f(frame*, const RegisterMap*)); // Memory operations - void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); // Sweeper operations void nmethods_do(CodeBlobClosure* cf); @@ -1852,7 +1852,7 @@ class CompilerThread : public JavaThread { // GC support // Apply "f->do_oop" to all root oops in "this". // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames - void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); #ifndef PRODUCT private: @@ -1921,9 +1921,9 @@ class Threads: AllStatic { // Apply "f->do_oop" to all root oops in all threads. // This version may only be called by sequential code. - static void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + static void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); // This version may be called by sequential or parallel code. - static void possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + static void possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); // This creates a list of GCTasks, one per thread. static void create_thread_roots_tasks(GCTaskQueue* q); // This creates a list of GCTasks, one per thread, for marking objects. diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index bdb508208d4..b2ccccc8f13 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -677,7 +677,7 @@ void VMThread::execute(VM_Operation* op) { } -void VMThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) { +void VMThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) { Thread::oops_do(f, cld_f, cf); _vm_queue->oops_do(f); } diff --git a/hotspot/src/share/vm/runtime/vmThread.hpp b/hotspot/src/share/vm/runtime/vmThread.hpp index d7a45b385a3..2682d9d5f24 100644 --- a/hotspot/src/share/vm/runtime/vmThread.hpp +++ b/hotspot/src/share/vm/runtime/vmThread.hpp @@ -126,7 +126,7 @@ class VMThread: public NamedThread { static VMThread* vm_thread() { return _vm_thread; } // GC support - void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf); + void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf); // Debugging void print_on(outputStream* st) const; From a235c50791fd6f8a9c3d45938dcf2764f6c21152 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 21 Feb 2014 10:19:09 +0100 Subject: [PATCH 164/265] 8035412: Cleanup ClassLoaderData::is_alive Reviewed-by: coleenp, mgerdin --- .../share/vm/classfile/classLoaderData.cpp | 22 ++++++++++++------- .../share/vm/classfile/classLoaderData.hpp | 9 +++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 892ea92fb00..81e519a2a07 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -73,7 +73,11 @@ ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) : _class_loader(h_class_loader()), - _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially + _is_anonymous(is_anonymous), + // An anonymous class loader data doesn't have anything to keep + // it from being unloaded during parsing of the anonymous class. + // The null-class-loader should always be kept alive. + _keep_alive(is_anonymous || h_class_loader.is_null()), _metaspace(NULL), _unloading(false), _klasses(NULL), _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), _next(NULL), _dependencies(dependencies), @@ -317,11 +321,15 @@ void ClassLoaderData::unload() { } } +oop ClassLoaderData::keep_alive_object() const { + assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive"); + return is_anonymous() ? _klasses->java_mirror() : class_loader(); +} + bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const { - bool alive = - is_anonymous() ? - is_alive_closure->do_object_b(_klasses->java_mirror()) : - class_loader() == NULL || is_alive_closure->do_object_b(class_loader()); + bool alive = keep_alive() // null class loader and incomplete anonymous klasses. + || is_alive_closure->do_object_b(keep_alive_object()); + assert(!alive || claimed(), "must be claimed"); return alive; } @@ -591,8 +599,6 @@ void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { if (ClassUnloading) { - ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim); - // keep any special CLDs alive. ClassLoaderDataGraph::keep_alive_oops_do(f, klass_closure, must_claim); } else { ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim); @@ -698,7 +704,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) { bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); MetadataOnStackMark md_on_stack; while (data != NULL) { - if (data->keep_alive() || data->is_alive(is_alive_closure)) { + if (data->is_alive(is_alive_closure)) { if (has_redefined_a_class) { data->classes_do(InstanceKlass::purge_previous_versions); } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index 9e76b50441f..1e92925d147 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -139,7 +139,7 @@ class ClassLoaderData : public CHeapObj { // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. bool _unloading; // true if this class loader goes away - bool _keep_alive; // if this CLD can be unloaded for anonymous loaders + bool _keep_alive; // if this CLD is kept alive without a keep_alive_object(). bool _is_anonymous; // if this CLD is for an anonymous class volatile int _claimed; // true if claimed, for example during GC traces. // To avoid applying oop closure more than once. @@ -230,13 +230,16 @@ class ClassLoaderData : public CHeapObj { oop class_loader() const { return _class_loader; } + // The object the GC is using to keep this ClassLoaderData alive. + oop keep_alive_object() const; + // Returns true if this class loader data is for a loader going away. bool is_unloading() const { assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded"); return _unloading; } - // Anonymous class loader data doesn't have anything to keep them from - // being unloaded during parsing the anonymous class. + + // Used to make sure that this CLD is not unloaded. void set_keep_alive(bool value) { _keep_alive = value; } unsigned int identity_hash() { From facc03d9f4dd23ded7124c8917401e39ad902d45 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 21 Feb 2014 10:35:19 +0100 Subject: [PATCH 165/265] 6411385: Trees.getPath does not work for constructors Enhancing TestTrees test to ensure proper function of Trees.getPath/getTree, fixing cases where getTree did not work properly. Co-authored-by: Dusan Balek Reviewed-by: jjg --- .../com/sun/tools/javac/api/JavacTrees.java | 17 +----- .../sun/tools/javac/model/JavacElements.java | 6 +- langtools/test/tools/javac/api/TestTrees.java | 56 +++++++++++++++++-- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java index 7152f05dbc1..eb4b43f3622 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,20 +269,7 @@ public class JavacTrees extends DocTrees { } public JCTree getTree(Element element) { - Symbol symbol = (Symbol) element; - TypeSymbol enclosing = symbol.enclClass(); - Env env = enter.getEnv(enclosing); - if (env == null) - return null; - JCClassDecl classNode = env.enclClass; - if (classNode != null) { - if (TreeInfo.symbolFor(classNode) == element) - return classNode; - for (JCTree node : classNode.getMembers()) - if (TreeInfo.symbolFor(node) == element) - return node; - } - return null; + return getTree(element, null); } public JCTree getTree(Element e, AnnotationMirror a) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java index d0a99d6f27a..b1a6cd19ba7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -193,13 +193,17 @@ public class JavacElements implements Elements { public void visitVarDef(JCVariableDecl tree) { result = tree.mods.annotations; } + @Override + public void visitTypeParameter(JCTypeParameter tree) { + result = tree.annotations; + } } Vis vis = new Vis(); tree.accept(vis); if (vis.result == null) return null; - List annos = sym.getRawAttributes(); + List annos = sym.getAnnotationMirrors(); return matchAnnoToTree(cast(Attribute.Compound.class, findme), annos, vis.result); diff --git a/langtools/test/tools/javac/api/TestTrees.java b/langtools/test/tools/javac/api/TestTrees.java index 4974bb447a9..a95e9a2e537 100644 --- a/langtools/test/tools/javac/api/TestTrees.java +++ b/langtools/test/tools/javac/api/TestTrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6346249 6392177 + * @bug 6346249 6392177 6411385 * @summary new Trees API */ @@ -51,6 +51,9 @@ public class TestTrees extends AbstractProcessor { @Anno int annoField; + @Anno + public TestTrees() { + } static final String testSrcDir = System.getProperty("test.src"); static final String testClassDir = System.getProperty("test.classes"); @@ -75,7 +78,7 @@ public class TestTrees extends AbstractProcessor { Iterable files = fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java"))); - Iterable opts = Arrays.asList("-d", "."); + Iterable opts = Arrays.asList("-d", ".", "-XDcompilePolicy=simple"); System.err.println("simple compilation, no processing"); JavacTask task = tool.getTask(out, fm, dl, opts, null, files); @@ -83,7 +86,8 @@ public class TestTrees extends AbstractProcessor { if (!task.call()) throw new AssertionError("compilation failed"); - opts = Arrays.asList("-d", ".", "-processorpath", testClassDir, "-processor", self); + opts = Arrays.asList("-d", ".", "-processorpath", testClassDir, "-processor", self, + "-XDcompilePolicy=simple"); System.err.println(); System.err.println("compilation with processing"); @@ -138,7 +142,7 @@ public class TestTrees extends AbstractProcessor { System.err.println("testAnnotation: " + e + " " + a); Tree tree = trees.getTree(e, a); - if (tree.getKind() != Tree.Kind.ANNOTATION) + if (tree.getKind() != Tree.Kind.ANNOTATION && tree.getKind() != Tree.Kind.TYPE_ANNOTATION) error("bad result from getTree"); TreePath path = trees.getPath(e, a); @@ -146,6 +150,36 @@ public class TestTrees extends AbstractProcessor { error("bad result from getPath"); } + void testAllDeclarations(Trees trees, CompilationUnitTree cut) { + new TreePathScanner() { + @Override public Void scan(Tree tree, Void p) { + if (tree == null) return null; + switch (tree.getKind()) { + case METHOD: case CLASS: case VARIABLE: case TYPE_PARAMETER: + TreePath path = new TreePath(getCurrentPath(), tree); + Element el = trees.getElement(path); + if (el == null) { + error("null element"); + } else { + TreePath inferred = trees.getPath(el); + if (inferred == null) { + error("null path"); + } else { + if (inferred.getLeaf() != path.getLeaf()) + error("bad result from getPath"); + } + if (trees.getTree(el) != path.getLeaf()) + error("bad result from getTree"); + for (AnnotationMirror m: el.getAnnotationMirrors()) { + testAnnotation(trees, el, m); + } + } + } + return super.scan(tree, p); + } + }.scan(cut, null); + } + void error(String msg) { if (messager != null) // annotation processing will happen in a separate instance/classloader @@ -202,6 +236,7 @@ public class TestTrees extends AbstractProcessor { switch (e.getKind()) { case ANALYZE: testElement(Trees.instance(task), e.getTypeElement()); + testAllDeclarations(Trees.instance(task), e.getCompilationUnit()); break; } } @@ -209,8 +244,19 @@ public class TestTrees extends AbstractProcessor { private final JavacTask task; } + public static class TestTypeParams<@Anno T extends CharSequence> { + public <@Anno T extends Object> TestTypeParams(T param) { } + public <@Anno T extends Number> void m(T param) { + int local; + try { + new String(); + } catch (Exception exc) { } + } + } } @Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE_PARAMETER, + ElementType.FIELD, ElementType.LOCAL_VARIABLE}) @interface Anno { } From 98b44a020b26b3284e5d5f5e525c0eda15fcbc19 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Fri, 21 Feb 2014 15:14:09 +0400 Subject: [PATCH 166/265] 6457406: javadoc doesn't handle properly in producing index pages Reviewed-by: jjg, bpatel, ksrini --- .../formats/html/HtmlDocletWriter.java | 10 ++- .../TestSingleQuotedLink.java | 75 +++++++++++++++++++ .../javadoc/testSingleQuotedLink/pkg1/C1.java | 29 +++++++ .../javadoc/testSingleQuotedLink/pkg1/C2.java | 31 ++++++++ .../testSingleQuotedLink/pkg1/package.html | 14 ++++ 5 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 langtools/test/com/sun/javadoc/testSingleQuotedLink/TestSingleQuotedLink.java create mode 100644 langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C1.java create mode 100644 langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C2.java create mode 100644 langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/package.html diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index db66e9a8e5e..bccbba16322 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -1713,9 +1713,13 @@ public class HtmlDocletWriter extends HtmlDocWriter { //might be missing '>' character because the href has an inline tag. break; } - if (textBuff.substring(begin, end).contains("\"")){ - begin = textBuff.indexOf("\"", begin) + 1; - end = textBuff.indexOf("\"", begin +1); + + String quote = textBuff.substring(begin, end); + quote = quote.contains("\"") ? "\"" : + quote.contains("\'") ? "\'" : null; + if (quote != null) { + begin = textBuff.indexOf(quote, begin) + 1; + end = textBuff.indexOf(quote, begin +1); if (begin == 0 || end == -1){ //Link is missing a quote. break; diff --git a/langtools/test/com/sun/javadoc/testSingleQuotedLink/TestSingleQuotedLink.java b/langtools/test/com/sun/javadoc/testSingleQuotedLink/TestSingleQuotedLink.java new file mode 100644 index 00000000000..ef8bc56db23 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSingleQuotedLink/TestSingleQuotedLink.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6457406 + * @summary Verify that a link in single quotes copied to the class-use page as is. + * @author Yuri Nesterenko + * @library ../lib/ + * @build JavadocTester TestSingleQuotedLink + * @run main TestSingleQuotedLink + */ +public class TestSingleQuotedLink extends JavadocTester { + + private static final String BUG_ID = "6457406"; + // We are testing the redirection algorithm with a known scenario when a writer is not forced to ignore it: "-use". + private static final String[][] TEST = { + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "" + } + }; + private static final String[][] NEGATED_TEST = { + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "pkg1/\'http://download.oracle.com/javase/8/docs/technotes/guides/indexC2.html\'>" + } + }; + private static final String[] ARGS = + new String[]{ + "-d", BUG_ID, "-sourcepath", SRC_DIR, "-use", "pkg1" + }; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestSingleQuotedLink tester = new TestSingleQuotedLink(); + run(tester, ARGS, TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C1.java b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C1.java new file mode 100644 index 00000000000..7c1faaf4aba --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C1.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +/** + * Class 1. This is a test. + */ +public class C1 {} diff --git a/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C2.java b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C2.java new file mode 100644 index 00000000000..40a65f2ea8f --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/C2.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +/** + * Class 2 refers to Here. + * This is a single quoted link. + */ +public class C2 extends C1 {} + diff --git a/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/package.html b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/package.html new file mode 100644 index 00000000000..ea1a8f38cfd --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSingleQuotedLink/pkg1/package.html @@ -0,0 +1,14 @@ + + +javax.management package + + + This is a test. +

+ + Another Test document 2. Single quotes also but as of now, package-summary writer excluded from redirection algorithm. + + @since 1.5 + + + From 2c18d040ba480575a9291fd65b97da840676d0ad Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Fri, 21 Feb 2014 16:57:21 +0400 Subject: [PATCH 167/265] 8032909: XSLT string-length returns incorrect length when string includes complementary chars Reviewed-by: joehw, dfuchs --- .../xalan/internal/xsltc/compiler/StringLengthCall.java | 7 ++++--- .../xalan/internal/xsltc/runtime/BasisLibrary.java | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringLengthCall.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringLengthCall.java index 104b16b38d1..212a6d86a54 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringLengthCall.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/StringLengthCall.java @@ -26,7 +26,7 @@ package com.sun.org.apache.xalan.internal.xsltc.compiler; import java.util.Vector; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; -import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; +import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; @@ -51,7 +51,8 @@ final class StringLengthCall extends FunctionCall { il.append(methodGen.loadContextNode()); Type.Node.translateTo(classGen, methodGen, Type.String); } - il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_CLASS, - "length", "()I"))); + il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, + "getStringLength", + "(Ljava/lang/String;)I"))); } } diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java index ddefee2fe0c..74acd2ad341 100644 --- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java +++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java @@ -1660,5 +1660,14 @@ public final class BasisLibrary { } + /** + * Utility method to calculate string-length as a number of code points, + * to avoid possible errors with string that contains + * complementary characters + */ + public static int getStringLength(String str) { + return str.codePointCount(0,str.length()); + } + //-- End utility functions } From 1dcf806682c32de9c67f1439df42d774e0b23e2f Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:39:18 -0800 Subject: [PATCH 168/265] Added tag jdk9-b03 for changeset 0ce00b83a208 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index fe1310f80db..45398d20075 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -245,3 +245,4 @@ cd3825b2983045784d6fc6d1729c799b08215752 jdk8-b120 1e1f86d5d4e22c15a9bf9f1581acddb8c59abae2 jdk9-b00 50669e45cec4491de0d921d3118a3fe2e767020a jdk9-b01 135f0c7af57ebace31383d8877f47e32172759ff jdk9-b02 +fd8d51bdf9aadf7ae83e65e8655c53581017c363 jdk9-b03 From 540d4e68597d45c6ebf6183565a3f5f1b569c791 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:39:27 -0800 Subject: [PATCH 169/265] Added tag jdk9-b03 for changeset 6a651a3acc5e --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 03c69ec949f..13a64cfd8b1 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -245,3 +245,4 @@ d6820a414f182a011a53a29a52370c696cd58dab jdk8-b118 a7d3638deb2f4e33217b1ecf889479e90f9e5b50 jdk9-b00 79a8136b18c1c6848f500088f5a4b39f262f082d jdk9-b01 8394993063135a42b63a94473280399fb2a13aa7 jdk9-b02 +d338b892a13db19b093f85cf5f949a4504e4d31f jdk9-b03 From ce71d7e2b2a9f045f4b0a234db9ea2f06ca31b6a Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:39:47 -0800 Subject: [PATCH 170/265] Added tag jdk9-b03 for changeset 69d4b2a482eb --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 9b4aa750ec2..71ad9311d10 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -405,3 +405,4 @@ fca262db9c4309f99d2f5542ab0780e45c2f1578 jdk8-b120 ce2d7e46f3c7e41241f3b407705a4071323a11ab jdk9-b00 050a626a88951140df874f7b163e304d07b6c296 jdk9-b01 b188446de75bda5fc52d102cddf242c3ef5ecbdf jdk9-b02 +b2fee789d23f3cdabb3db4e51af43038e5692d3a jdk9-b03 From 4b310bb6d09ab0c4e211afa22367bcf3ae08aa2a Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:40:06 -0800 Subject: [PATCH 171/265] Added tag jdk9-b03 for changeset ba5629320bb2 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index bca7de34ab8..89dfe4cfb54 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -245,3 +245,4 @@ e4e5069250e717defcb556e2f6be291460988c51 jdk8-b118 4045edd35e8ba73bfdc23ce8961b9640d4145fe5 jdk9-b00 e5256f530a9b5f2d677ca245de44a617ffb58f52 jdk9-b01 02f60a253e15240087c043bad77a106792e4d56a jdk9-b02 +fb92ed0399424193f444489ad49a16748816dc12 jdk9-b03 From 33769b38e5b190877c87288cedc3da3b7f90a700 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:40:10 -0800 Subject: [PATCH 172/265] Added tag jdk9-b03 for changeset 973ca15c0167 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index a6c41cf6400..8e843fe4b59 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -248,3 +248,4 @@ bc622ba563f9316f981c11c3a260f4c3fdc5ef07 jdk8-b122 32050ab53c8a8e4cb09f04b88db78258a480fb61 jdk9-b00 9c9fabbcd3d526d7ca29165169155f49a107533a jdk9-b01 efe2bc258c78af49de9517a4a5699d3a2e630c44 jdk9-b02 +1cd9786257ed4f82a3371fd606b162e5bb6fcd81 jdk9-b03 From a0bac0c9c01a07c4a09d982502d89c7acb2c9a43 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:40:24 -0800 Subject: [PATCH 173/265] Added tag jdk9-b03 for changeset 4a4630af7adf --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 5a7ffba22b9..950784a2233 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -245,3 +245,4 @@ d31cd980e1da31fa496a359caaf1a165aeb5791a jdk8-b120 27b384262cba51dd0fe3e3534820189b46abc8cb jdk9-b00 3b4ac8d1b76fc6bec9815f0ab714f15b552e4c7b jdk9-b01 8c8275426a3207d91393354f7a7f9bc362ec25cf jdk9-b02 +4111af6151ed8ca8e3f5603c69729a68427e1d5b jdk9-b03 From 7d41c598a4d09c77ea04102a3c1708bfc2ed427f Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:40:51 -0800 Subject: [PATCH 174/265] Added tag jdk9-b03 for changeset 2740ebeb238c --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 7713b53738e..ab6c1e2e32a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -245,3 +245,4 @@ b3d7e86a06474fe5100a7b15a95eaa10d41509a6 jdk8-b120 afe63d41c699e0e2ee910ef20c41b60603c852a1 jdk9-b00 077c12d527fb5531c59666c1f84000fc1245a260 jdk9-b01 f2c58a337c8aaa1ce84dfa8a8e8c5d4c8c1e12fa jdk9-b02 +151222468d1d04ce6613d33efa3d45bfaf53e3e5 jdk9-b03 From 090c57164e1842f0a69b3d2c744d05e8c3f959db Mon Sep 17 00:00:00 2001 From: David Katleman Date: Fri, 21 Feb 2014 11:40:55 -0800 Subject: [PATCH 175/265] Added tag jdk9-b03 for changeset fdf4454a8368 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 6236fcba08e..f2335745fca 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -236,3 +236,4 @@ c3343930c73c58a22c1d58719bb988aeb25a871f jdk8-b119 32631eed0fad2b31346eb41b29a50227bd29e2ec jdk9-b00 65347535840f045f2cd4341d7466c51009b1b06f jdk9-b01 b3517e51f40477f10db8bc30a557aa0ea712c274 jdk9-b02 +832f89ff25d903c45cfc994553f1ade8821a4398 jdk9-b03 From 68857c9469ef05c3ca8991f83de4cfd35026bf71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Sat, 22 Feb 2014 10:22:05 +0100 Subject: [PATCH 176/265] 8035493: JVMTI PopFrame capability must instruct compilers not to prune locals Reviewed-by: kvn, sla, coleenp, sspitsyn --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 6 +-- hotspot/src/share/vm/c1/c1_Instruction.cpp | 2 +- hotspot/src/share/vm/c1/c1_ValueStack.cpp | 2 +- hotspot/src/share/vm/c1/c1_ValueStack.hpp | 2 +- hotspot/src/share/vm/ci/ciEnv.cpp | 43 +++++++++++++++++---- hotspot/src/share/vm/ci/ciEnv.hpp | 4 +- hotspot/src/share/vm/ci/ciMethod.cpp | 2 +- hotspot/src/share/vm/opto/c2compiler.cpp | 2 +- hotspot/src/share/vm/opto/graphKit.cpp | 2 +- 9 files changed, 48 insertions(+), 17 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 8d7d4e36d2a..7cb6d3dfa47 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -2276,7 +2276,7 @@ XHandlers* GraphBuilder::handle_exception(Instruction* instruction) { if (!has_handler() && (!instruction->needs_exception_state() || instruction->exception_state() != NULL)) { assert(instruction->exception_state() == NULL || instruction->exception_state()->kind() == ValueStack::EmptyExceptionState - || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->jvmti_can_access_local_variables()), + || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->should_retain_local_variables()), "exception_state should be of exception kind"); return new XHandlers(); } @@ -2367,7 +2367,7 @@ XHandlers* GraphBuilder::handle_exception(Instruction* instruction) { // This scope and all callees do not handle exceptions, so the local // variables of this scope are not needed. However, the scope itself is // required for a correct exception stack trace -> clear out the locals. - if (_compilation->env()->jvmti_can_access_local_variables()) { + if (_compilation->env()->should_retain_local_variables()) { cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci()); } else { cur_state = cur_state->copy(ValueStack::EmptyExceptionState, cur_state->bci()); @@ -3251,7 +3251,7 @@ ValueStack* GraphBuilder::copy_state_exhandling_with_bci(int bci) { ValueStack* GraphBuilder::copy_state_for_exception_with_bci(int bci) { ValueStack* s = copy_state_exhandling_with_bci(bci); if (s == NULL) { - if (_compilation->env()->jvmti_can_access_local_variables()) { + if (_compilation->env()->should_retain_local_variables()) { s = state()->copy(ValueStack::ExceptionState, bci); } else { s = state()->copy(ValueStack::EmptyExceptionState, bci); diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 99d00bdec27..a77b22ff14c 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -76,7 +76,7 @@ Instruction::Condition Instruction::negate(Condition cond) { void Instruction::update_exception_state(ValueStack* state) { if (state != NULL && (state->kind() == ValueStack::EmptyExceptionState || state->kind() == ValueStack::ExceptionState)) { - assert(state->kind() == ValueStack::EmptyExceptionState || Compilation::current()->env()->jvmti_can_access_local_variables(), "unexpected state kind"); + assert(state->kind() == ValueStack::EmptyExceptionState || Compilation::current()->env()->should_retain_local_variables(), "unexpected state kind"); _exception_state = state; } else { _exception_state = NULL; diff --git a/hotspot/src/share/vm/c1/c1_ValueStack.cpp b/hotspot/src/share/vm/c1/c1_ValueStack.cpp index 44a8e6d529f..fcf8ba2ce46 100644 --- a/hotspot/src/share/vm/c1/c1_ValueStack.cpp +++ b/hotspot/src/share/vm/c1/c1_ValueStack.cpp @@ -52,7 +52,7 @@ ValueStack::ValueStack(ValueStack* copy_from, Kind kind, int bci) , _stack() , _locks(copy_from->locks_size()) { - assert(kind != EmptyExceptionState || !Compilation::current()->env()->jvmti_can_access_local_variables(), "need locals"); + assert(kind != EmptyExceptionState || !Compilation::current()->env()->should_retain_local_variables(), "need locals"); if (kind != EmptyExceptionState) { // only allocate space if we need to copy the locals-array _locals = Values(copy_from->locals_size()); diff --git a/hotspot/src/share/vm/c1/c1_ValueStack.hpp b/hotspot/src/share/vm/c1/c1_ValueStack.hpp index a3c8b27a964..8340adbd289 100644 --- a/hotspot/src/share/vm/c1/c1_ValueStack.hpp +++ b/hotspot/src/share/vm/c1/c1_ValueStack.hpp @@ -75,7 +75,7 @@ class ValueStack: public CompilationResourceObj { void set_caller_state(ValueStack* s) { assert(kind() == EmptyExceptionState || - (Compilation::current()->env()->jvmti_can_access_local_variables() && kind() == ExceptionState), + (Compilation::current()->env()->should_retain_local_variables() && kind() == ExceptionState), "only EmptyExceptionStates can be modified"); _caller_state = s; } diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index dcb3472802c..17764f12ad1 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -136,6 +136,11 @@ ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) { _ClassCastException_instance = NULL; _the_null_string = NULL; _the_min_jint_string = NULL; + + _jvmti_can_hotswap_or_post_breakpoint = false; + _jvmti_can_access_local_variables = false; + _jvmti_can_post_on_exceptions = false; + _jvmti_can_pop_frame = false; } ciEnv::ciEnv(Arena* arena) { @@ -186,6 +191,11 @@ ciEnv::ciEnv(Arena* arena) { _ClassCastException_instance = NULL; _the_null_string = NULL; _the_min_jint_string = NULL; + + _jvmti_can_hotswap_or_post_breakpoint = false; + _jvmti_can_access_local_variables = false; + _jvmti_can_post_on_exceptions = false; + _jvmti_can_pop_frame = false; } ciEnv::~ciEnv() { @@ -205,6 +215,31 @@ void ciEnv::cache_jvmti_state() { _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint(); _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables(); _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions(); + _jvmti_can_pop_frame = JvmtiExport::can_pop_frame(); +} + +bool ciEnv::should_retain_local_variables() const { + return _jvmti_can_access_local_variables || _jvmti_can_pop_frame; +} + +bool ciEnv::jvmti_state_changed() const { + if (!_jvmti_can_access_local_variables && + JvmtiExport::can_access_local_variables()) { + return true; + } + if (!_jvmti_can_hotswap_or_post_breakpoint && + JvmtiExport::can_hotswap_or_post_breakpoint()) { + return true; + } + if (!_jvmti_can_post_on_exceptions && + JvmtiExport::can_post_on_exceptions()) { + return true; + } + if (!_jvmti_can_pop_frame && + JvmtiExport::can_pop_frame()) { + return true; + } + return false; } // ------------------------------------------------------------------ @@ -940,13 +975,7 @@ void ciEnv::register_method(ciMethod* target, No_Safepoint_Verifier nsv; // Change in Jvmti state may invalidate compilation. - if (!failing() && - ( (!jvmti_can_hotswap_or_post_breakpoint() && - JvmtiExport::can_hotswap_or_post_breakpoint()) || - (!jvmti_can_access_local_variables() && - JvmtiExport::can_access_local_variables()) || - (!jvmti_can_post_on_exceptions() && - JvmtiExport::can_post_on_exceptions()) )) { + if (!failing() && jvmti_state_changed()) { record_failure("Jvmti state change invalidated dependencies"); } diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index 5a0bd1f1352..2b847f0af3c 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -69,6 +69,7 @@ private: bool _jvmti_can_hotswap_or_post_breakpoint; bool _jvmti_can_access_local_variables; bool _jvmti_can_post_on_exceptions; + bool _jvmti_can_pop_frame; // Cache DTrace flags bool _dtrace_extended_probes; @@ -332,8 +333,9 @@ public: // Cache Jvmti state void cache_jvmti_state(); + bool jvmti_state_changed() const; + bool should_retain_local_variables() const; bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; } - bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables; } bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions; } // Cache DTrace flags diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 923331edee3..86f1ed31bef 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -412,7 +412,7 @@ MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) { // information. MethodLivenessResult ciMethod::liveness_at_bci(int bci) { MethodLivenessResult result = raw_liveness_at_bci(bci); - if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) { + if (CURRENT_ENV->should_retain_local_variables() || DeoptimizeALot || CompileTheWorld) { // Keep all locals live for the user's edification and amusement. result.at_put_range(0, result.size(), true); } diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 7fa7918263e..1bf1e9ce58d 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -111,7 +111,7 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { assert(is_initialized(), "Compiler thread must be initialized"); bool subsume_loads = SubsumeLoads; - bool do_escape_analysis = DoEscapeAnalysis && !env->jvmti_can_access_local_variables(); + bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables(); bool eliminate_boxing = EliminateAutoBox; while (!env->failing()) { // Attempt to compile while subsuming loads into machine instructions. diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index c30cdc12c82..e3602f5ef21 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -863,7 +863,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { } } - if (env()->jvmti_can_access_local_variables()) { + if (env()->should_retain_local_variables()) { // At any safepoint, this method can get breakpointed, which would // then require an immediate deoptimization. can_prune_locals = false; // do not prune locals From c7af5cd60b8cce03c2a19bf81743ef9960f4f3c2 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sat, 22 Feb 2014 17:42:10 +0000 Subject: [PATCH 177/265] 8034143: javac, subclasses of Infer.IncorporationStep should implement the accepts() method Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Infer.java | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 125eb127d99..6e0a72d0739 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -583,11 +583,17 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && uv.getBounds(InferenceBound.EQ).nonEmpty(); + } }, /** * Check consistency of equality constraints. */ EQ_CHECK() { + @Override public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { Infer infer = inferenceContext.infer(); for (Type e : uv.getBounds(InferenceBound.EQ)) { @@ -604,6 +610,11 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && uv.getBounds(InferenceBound.EQ).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha <: T} and {@code alpha :> S} @@ -618,6 +629,13 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.UPPER).nonEmpty() && + uv.getBounds(InferenceBound.LOWER).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha <: T} and {@code alpha == S} @@ -632,6 +650,13 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.EQ).nonEmpty() && + uv.getBounds(InferenceBound.UPPER).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha :> S} and {@code alpha == T} @@ -646,6 +671,13 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.EQ).nonEmpty() && + uv.getBounds(InferenceBound.LOWER).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha == S} and {@code alpha == T} @@ -662,6 +694,12 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.EQ).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha <: beta} propagate lower bounds @@ -688,6 +726,12 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.UPPER).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha :> beta} propagate lower bounds @@ -714,6 +758,12 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.LOWER).nonEmpty(); + } }, /** * Given a bound set containing {@code alpha == beta} propagate lower/upper @@ -748,6 +798,12 @@ public class Infer { } } } + + @Override + boolean accepts(UndetVar uv, InferenceContext inferenceContext) { + return !uv.isCaptured() && + uv.getBounds(InferenceBound.EQ).nonEmpty(); + } }; abstract void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn); From cdc5c0c966aaca21635695604983777175d1c441 Mon Sep 17 00:00:00 2001 From: Axel Siebenborn Date: Sun, 23 Feb 2014 22:36:19 -0800 Subject: [PATCH 178/265] 8034867: Object references from expression stack are not visible as roots via jvmti FollowReferences and HeapDump The heap walking is inconsistent without following references from expression stack, so need to fix it Reviewed-by: coleenp, sspitsyn --- hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 17 +++++++++++++++++ hotspot/src/share/vm/services/heapDumper.cpp | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 8f2e1af6e44..aeb8f58e7ca 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -3081,6 +3081,23 @@ inline bool VM_HeapWalkOperation::collect_stack_roots(JavaThread* java_thread, } } } + + StackValueCollection* exprs = jvf->expressions(); + for (int index=0; index < exprs->size(); index++) { + if (exprs->at(index)->type() == T_OBJECT) { + oop o = exprs->obj_at(index)(); + if (o == NULL) { + continue; + } + + // stack reference + if (!CallbackInvoker::report_stack_ref_root(thread_tag, tid, depth, method, + bci, locals->size() + index, o)) { + return false; + } + } + } + } else { blk->set_context(thread_tag, tid, depth, method); if (is_top_frame) { diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index c0d01048924..39c9a395d73 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1604,6 +1604,18 @@ int VM_HeapDumper::do_thread(JavaThread* java_thread, u4 thread_serial_num) { } } } + StackValueCollection *exprs = jvf->expressions(); + for(int index = 0; index < exprs->size(); index++) { + if (exprs->at(index)->type() == T_OBJECT) { + oop o = exprs->obj_at(index)(); + if (o != NULL) { + writer()->write_u1(HPROF_GC_ROOT_JAVA_FRAME); + writer()->write_objectID(o); + writer()->write_u4(thread_serial_num); + writer()->write_u4((u4) (stack_depth + extra_frames)); + } + } + } } else { // native frame if (stack_depth == 0) { From 6c588725c1921a3b99d05c269e5acddace9202d0 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 24 Feb 2014 09:40:21 +0100 Subject: [PATCH 179/265] 8027559: Decrease code size and templatizing in G1ParCopyClosure::do_oop_work Move methods that are not dependent on any of G1ParCopyClosure's template parameters into G1ParCopyHelper. Further remove unused methods and members of the class hierarchy. Reviewed-by: mgerdin, stefank --- hotspot/make/excludeSrc.make | 2 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 17 +++------- .../vm/gc_implementation/g1/g1OopClosures.cpp | 31 +++++++++++++++++ .../vm/gc_implementation/g1/g1OopClosures.hpp | 33 ++++++++----------- .../g1/g1OopClosures.inline.hpp | 2 +- 5 files changed, 51 insertions(+), 34 deletions(-) create mode 100644 hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make index a95dc1b114c..24f1fa20ec3 100644 --- a/hotspot/make/excludeSrc.make +++ b/hotspot/make/excludeSrc.make @@ -86,7 +86,7 @@ ifeq ($(INCLUDE_ALL_GCS), false) concurrentMark.cpp concurrentMarkThread.cpp dirtyCardQueue.cpp g1AllocRegion.cpp \ g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \ g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \ - g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp \ + g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \ g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \ g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \ ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index c9e43171368..35ade47353e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4653,14 +4653,10 @@ void G1ParScanThreadState::trim_queue() { G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), - _par_scan_state(par_scan_state), - _worker_id(par_scan_state->queue_num()), - _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), - _mark_in_progress(_g1->mark_in_progress()) { } + _g1(g1), _par_scan_state(par_scan_state), + _worker_id(par_scan_state->queue_num()) { } -template -void G1ParCopyClosure::mark_object(oop obj) { +void G1ParCopyHelper::mark_object(oop obj) { #ifdef ASSERT HeapRegion* hr = _g1->heap_region_containing(obj); assert(hr != NULL, "sanity"); @@ -4671,9 +4667,7 @@ void G1ParCopyClosure::mark_object(oop obj) { _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); } -template -void G1ParCopyClosure - ::mark_forwarded_object(oop from_obj, oop to_obj) { +void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { #ifdef ASSERT assert(from_obj->is_forwarded(), "from obj should be forwarded"); assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee"); @@ -4794,8 +4788,7 @@ void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) { template template -void G1ParCopyClosure -::do_oop_work(T* p) { +void G1ParCopyClosure::do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); assert(_worker_id == _par_scan_state->queue_num(), "sanity"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp new file mode 100644 index 00000000000..a30b00416bc --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1OopClosures.inline.hpp" + +G1ParCopyHelper::G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : + G1ParClosureSuper(g1, par_scan_state), _scanned_klass(NULL), + _cm(_g1->concurrent_mark()) {} diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index bda11dc6b98..27264e3369c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -48,12 +48,8 @@ public: class G1ParClosureSuper : public OopsInHeapRegionClosure { protected: G1CollectedHeap* _g1; - G1RemSet* _g1_rem; - ConcurrentMark* _cm; G1ParScanThreadState* _par_scan_state; uint _worker_id; - bool _during_initial_mark; - bool _mark_in_progress; public: G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state); bool apply_to_weak_ref_discovered_field() { return true; } @@ -133,12 +129,21 @@ public: // Add back base class for metadata class G1ParCopyHelper : public G1ParClosureSuper { +protected: Klass* _scanned_klass; + ConcurrentMark* _cm; + // Mark the object if it's not already marked. This is used to mark + // objects pointed to by roots that are guaranteed not to move + // during the GC (i.e., non-CSet objects). It is MT-safe. + void mark_object(oop obj); + + // Mark the object if it's not already marked. This is used to mark + // objects pointed to by roots that have been forwarded during a + // GC. It is MT-safe. + void mark_forwarded_object(oop from_obj, oop to_obj); public: - G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - _scanned_klass(NULL), - G1ParClosureSuper(g1, par_scan_state) {} + G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state); void set_scanned_klass(Klass* k) { _scanned_klass = k; } template void do_klass_barrier(T* p, oop new_obj); @@ -150,16 +155,6 @@ class G1ParCopyClosure : public G1ParCopyHelper { template void do_oop_work(T* p); protected: - // Mark the object if it's not already marked. This is used to mark - // objects pointed to by roots that are guaranteed not to move - // during the GC (i.e., non-CSet objects). It is MT-safe. - void mark_object(oop obj); - - // Mark the object if it's not already marked. This is used to mark - // objects pointed to by roots that have been forwarded during a - // GC. It is MT-safe. - void mark_forwarded_object(oop from_obj, oop to_obj); - oop copy_to_survivor_space(oop obj); public: @@ -172,9 +167,7 @@ public: G1ParScanClosure* scanner() { return &_scanner; } - template void do_oop_nv(T* p) { - do_oop_work(p); - } + template void do_oop_nv(T* p) { do_oop_work(p); } virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index ab1bd83eab4..bb93ef84866 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -82,7 +82,7 @@ inline void G1ParScanClosure::do_oop_nv(T* p) { _par_scan_state->push_on_queue(p); } else { - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); + _par_scan_state->update_rs(_from, p, _worker_id); } } } From dbc8581147bab8dd5aa15b75b84688e4395d6126 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 24 Feb 2014 09:40:49 +0100 Subject: [PATCH 180/265] 8035326: Assume non-NULL references in G1CollectedHeap::in_cset_fast_test Remove the assumption that G1CollectedHeap::in_cset_fast_test needs to check for NULL references. Most of the time this is not required, making the code doing this check multiple times. Reviewed-by: stefank, mgerdin, jmasa --- .../gc_implementation/g1/g1CollectedHeap.cpp | 13 ++++++--- .../gc_implementation/g1/g1CollectedHeap.hpp | 27 +++++++++---------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 35ade47353e..88f47fb11de 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4789,11 +4789,16 @@ void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) { template template void G1ParCopyClosure::do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); + T heap_oop = oopDesc::load_heap_oop(p); + + if (oopDesc::is_null(heap_oop)) { + return; + } + + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); assert(_worker_id == _par_scan_state->queue_num(), "sanity"); - // here the null check is implicit in the cset_fast_test() test if (_g1->in_cset_fast_test(obj)) { oop forwardee; if (obj->is_forwarded()) { @@ -4816,12 +4821,12 @@ void G1ParCopyClosure::do_oop_work(T* p) { // The object is not in collection set. If we're a root scanning // closure during an initial mark pause (i.e. do_mark_object will // be true) then attempt to mark the object. - if (do_mark_object && _g1->is_in_g1_reserved(obj)) { + if (do_mark_object) { mark_object(obj); } } - if (barrier == G1BarrierEvac && obj != NULL) { + if (barrier == G1BarrierEvac) { _par_scan_state->update_rs(_from, p, _worker_id); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 45caab039ea..ac81a06b536 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -698,23 +698,20 @@ public: } // This is a fast test on whether a reference points into the - // collection set or not. It does not assume that the reference - // points into the heap; if it doesn't, it will return false. + // collection set or not. Assume that the reference + // points into the heap. bool in_cset_fast_test(oop obj) { assert(_in_cset_fast_test != NULL, "sanity"); - if (_g1_committed.contains((HeapWord*) obj)) { - // no need to subtract the bottom of the heap from obj, - // _in_cset_fast_test is biased - uintx index = cast_from_oop(obj) >> HeapRegion::LogOfHRGrainBytes; - bool ret = _in_cset_fast_test[index]; - // let's make sure the result is consistent with what the slower - // test returns - assert( ret || !obj_in_cs(obj), "sanity"); - assert(!ret || obj_in_cs(obj), "sanity"); - return ret; - } else { - return false; - } + assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, (HeapWord*)obj)); + // no need to subtract the bottom of the heap from obj, + // _in_cset_fast_test is biased + uintx index = cast_from_oop(obj) >> HeapRegion::LogOfHRGrainBytes; + bool ret = _in_cset_fast_test[index]; + // let's make sure the result is consistent with what the slower + // test returns + assert( ret || !obj_in_cs(obj), "sanity"); + assert(!ret || obj_in_cs(obj), "sanity"); + return ret; } void clear_cset_fast_test() { From 2ae60596ed9cbe8099669d7f57b3efc78e6e8676 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 24 Feb 2014 09:41:04 +0100 Subject: [PATCH 181/265] 8035329: Move G1ParCopyClosure::copy_to_survivor_space into G1ParScanThreadState Move G1ParCopyClosure::copy_to_survivor_space to decrease code size. Reviewed-by: stefank, jmasa --- .../gc_implementation/g1/g1CollectedHeap.cpp | 40 +++++++++---------- .../gc_implementation/g1/g1CollectedHeap.hpp | 6 ++- .../vm/gc_implementation/g1/g1OopClosures.hpp | 8 +--- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 88f47fb11de..aacb4969da3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4534,7 +4534,7 @@ HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose, G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : ParGCAllocBuffer(gclab_word_size), _retired(false) { } -G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num) +G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp) : _g1h(g1h), _refs(g1h->task_queue(queue_num)), _dcq(&g1h->dirty_card_queue_set()), @@ -4544,7 +4544,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num) _term_attempts(0), _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)), _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)), - _age_table(false), + _age_table(false), _scanner(g1h, this, rp), _strong_roots_time(0), _term_time(0), _alloc_buffer_waste(0), _undo_waste(0) { // we allocate G1YoungSurvRateNumRegions plus one entries, since @@ -4689,27 +4689,25 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); } -template -oop G1ParCopyClosure - ::copy_to_survivor_space(oop old) { +oop G1ParScanThreadState::copy_to_survivor_space(oop const old) { size_t word_sz = old->size(); - HeapRegion* from_region = _g1->heap_region_containing_raw(old); + HeapRegion* from_region = _g1h->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... int young_index = from_region->young_index_in_cset()+1; assert( (from_region->is_young() && young_index > 0) || (!from_region->is_young() && young_index == 0), "invariant" ); - G1CollectorPolicy* g1p = _g1->g1_policy(); + G1CollectorPolicy* g1p = _g1h->g1_policy(); markOop m = old->mark(); int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() : m->age(); GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, word_sz); - HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); + HeapWord* obj_ptr = allocate(alloc_purpose, word_sz); #ifndef PRODUCT // Should this evacuation fail? - if (_g1->evacuation_should_fail()) { + if (_g1h->evacuation_should_fail()) { if (obj_ptr != NULL) { - _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz); + undo_allocation(alloc_purpose, obj_ptr, word_sz); obj_ptr = NULL; } } @@ -4718,7 +4716,7 @@ oop G1ParCopyClosure if (obj_ptr == NULL) { // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. - return _g1->handle_evacuation_failure_par(_par_scan_state, old); + return _g1h->handle_evacuation_failure_par(this, old); } oop obj = oop(obj_ptr); @@ -4751,12 +4749,12 @@ oop G1ParCopyClosure m = m->incr_age(); obj->set_mark(m); } - _par_scan_state->age_table()->add(obj, word_sz); + age_table()->add(obj, word_sz); } else { obj->set_mark(m); } - size_t* surv_young_words = _par_scan_state->surviving_young_words(); + size_t* surv_young_words = surviving_young_words(); surv_young_words[young_index] += word_sz; if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { @@ -4765,15 +4763,15 @@ oop G1ParCopyClosure // length field of the from-space object. arrayOop(obj)->set_length(0); oop* old_p = set_partial_array_mask(old); - _par_scan_state->push_on_queue(old_p); + push_on_queue(old_p); } else { // No point in using the slower heap_region_containing() method, // given that we know obj is in the heap. - _scanner.set_region(_g1->heap_region_containing_raw(obj)); + _scanner.set_region(_g1h->heap_region_containing_raw(obj)); obj->oop_iterate_backwards(&_scanner); } } else { - _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz); + undo_allocation(alloc_purpose, obj_ptr, word_sz); obj = forward_ptr; } return obj; @@ -4804,7 +4802,7 @@ void G1ParCopyClosure::do_oop_work(T* p) { if (obj->is_forwarded()) { forwardee = obj->forwardee(); } else { - forwardee = copy_to_survivor_space(obj); + forwardee = _par_scan_state->copy_to_survivor_space(obj); } assert(forwardee != NULL, "forwardee should not be NULL"); oopDesc::encode_store_heap_oop(p, forwardee); @@ -5023,7 +5021,7 @@ public: ReferenceProcessor* rp = _g1h->ref_processor_stw(); - G1ParScanThreadState pss(_g1h, worker_id); + G1ParScanThreadState pss(_g1h, worker_id, rp); G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp); G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp); G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp); @@ -5454,7 +5452,7 @@ public: G1STWIsAliveClosure is_alive(_g1h); - G1ParScanThreadState pss(_g1h, worker_id); + G1ParScanThreadState pss(_g1h, worker_id, NULL); G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); @@ -5566,7 +5564,7 @@ public: ResourceMark rm; HandleMark hm; - G1ParScanThreadState pss(_g1h, worker_id); + G1ParScanThreadState pss(_g1h, worker_id, NULL); G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, NULL); @@ -5692,7 +5690,7 @@ void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) { // JNI refs. // Use only a single queue for this PSS. - G1ParScanThreadState pss(this, 0); + G1ParScanThreadState pss(this, 0, NULL); // We do not embed a reference processor in the copying/scanning // closures while we're actually processing the discovered diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index ac81a06b536..1938f290c3a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1875,6 +1875,8 @@ protected: G1ParGCAllocBufferContainer* _alloc_buffers[GCAllocPurposeCount]; ageTable _age_table; + G1ParScanClosure _scanner; + size_t _alloc_buffer_waste; size_t _undo_waste; @@ -1927,7 +1929,7 @@ protected: } public: - G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num); + G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); ~G1ParScanThreadState() { FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC); @@ -2062,6 +2064,8 @@ public: } } + oop copy_to_survivor_space(oop const obj); + template void deal_with_reference(T* ref_to_scan) { if (has_partial_array_mask(ref_to_scan)) { _partial_scan_cl->do_oop_nv(ref_to_scan); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 27264e3369c..5eb5691c98b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -151,22 +151,16 @@ protected: template class G1ParCopyClosure : public G1ParCopyHelper { - G1ParScanClosure _scanner; +private: template void do_oop_work(T* p); -protected: - oop copy_to_survivor_space(oop obj); - public: G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) : - _scanner(g1, par_scan_state, rp), G1ParCopyHelper(g1, par_scan_state) { assert(_ref_processor == NULL, "sanity"); } - G1ParScanClosure* scanner() { return &_scanner; } - template void do_oop_nv(T* p) { do_oop_work(p); } virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } From 605e69a0dcd59e046263e95ff5646d5b7864c5d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Mon, 24 Feb 2014 13:29:14 +0100 Subject: [PATCH 182/265] 8035650: Exclude AIX from VS.NET make/windows/projectcreator.make Reviewed-by: dholmes, sla --- hotspot/make/windows/makefiles/projectcreator.make | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index d512796f8fe..f4ee4d14236 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -72,6 +72,7 @@ ProjectCreatorIncludesPRIVATE=\ -ignorePath arm \ -ignorePath ppc \ -ignorePath zero \ + -ignorePath aix \ -hidePath .hg From 2b758971764e8045bdcd737a0eef89742e5f4657 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 24 Feb 2014 10:28:22 +0100 Subject: [PATCH 183/265] 4505697: nsk/jdi/ExceptionEvent/_itself_/exevent006 and exevent008 tests fail with InvocationTargetException Reviewed-by: dcubed, dholmes, sspitsyn --- hotspot/src/share/vm/oops/instanceKlass.cpp | 7 +++++++ hotspot/src/share/vm/prims/jvm.cpp | 6 +++++- hotspot/src/share/vm/prims/jvmtiExport.cpp | 9 +++++++++ hotspot/src/share/vm/prims/jvmtiExport.hpp | 1 + hotspot/src/share/vm/runtime/reflection.cpp | 12 ++++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 62f7ffbf370..879835051c6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -49,6 +49,7 @@ #include "prims/jvmtiExport.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/jvmtiRedefineClasses.hpp" +#include "prims/jvmtiThreadState.hpp" #include "prims/methodComparator.hpp" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" @@ -862,10 +863,16 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { // Step 10 and 11 Handle e(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; + // JVMTI has already reported the pending exception + // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError + JvmtiExport::clear_detected_exception((JavaThread*)THREAD); { EXCEPTION_MARK; this_oop->set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below + // JVMTI has already reported the pending exception + // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError + JvmtiExport::clear_detected_exception((JavaThread*)THREAD); } DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait); if (e->is_a(SystemDictionary::Error_klass())) { diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index e26fd27d481..5003db9119a 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1241,7 +1241,11 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job if (HAS_PENDING_EXCEPTION) { pending_exception = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - + // JVMTI has already reported the pending exception + // JVMTI internal flag reset is needed in order to report PrivilegedActionException + if (THREAD->is_Java_thread()) { + JvmtiExport::clear_detected_exception((JavaThread*) THREAD); + } if ( pending_exception->is_a(SystemDictionary::Exception_klass()) && !pending_exception->is_a(SystemDictionary::RuntimeException_klass())) { // Throw a java.security.PrivilegedActionException(Exception e) exception diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 65039188c7b..8aacad27e83 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2161,6 +2161,15 @@ void JvmtiExport::cleanup_thread(JavaThread* thread) { } } +void JvmtiExport::clear_detected_exception(JavaThread* thread) { + assert(JavaThread::current() == thread, "thread is not current"); + + JvmtiThreadState* state = thread->jvmti_thread_state(); + if (state != NULL) { + state->clear_exception_detected(); + } +} + void JvmtiExport::oops_do(OopClosure* f) { JvmtiCurrentBreakpoints::oops_do(f); JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f); diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index d2a7dec71fd..4b1ff34cf61 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -363,6 +363,7 @@ class JvmtiExport : public AllStatic { } static void cleanup_thread (JavaThread* thread) NOT_JVMTI_RETURN; + static void clear_detected_exception (JavaThread* thread) NOT_JVMTI_RETURN; static void oops_do(OopClosure* f) NOT_JVMTI_RETURN; static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) NOT_JVMTI_RETURN; diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index dadcf60263f..de707164d03 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -36,6 +36,7 @@ #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "prims/jvm.h" +#include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -941,6 +942,11 @@ oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, // Method resolution threw an exception; wrap it in an InvocationTargetException oop resolution_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; + // 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); + } JavaCallArguments args(Handle(THREAD, resolution_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), @@ -1073,6 +1079,12 @@ oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, // Method threw an exception; wrap it in an InvocationTargetException oop target_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; + // 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); + } + JavaCallArguments args(Handle(THREAD, target_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), From 7de1730b10889641fd3ee8918efd9fbaacc2c068 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 24 Feb 2014 10:45:15 +0100 Subject: [PATCH 184/265] 8034948: Back out JDK-6976350 since it does not fix any issue Revert JDK-6976350 because it does not improve PLAB fragmentation. To the contrary, it tends to increase the amount of wasted space with many threads. Reviewed-by: brutisso --- .../gc_implementation/g1/g1CollectedHeap.hpp | 113 +++--------------- .../shared/parGCAllocBuffer.hpp | 2 +- 2 files changed, 17 insertions(+), 98 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 1938f290c3a..c1601e1c8a6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -606,6 +606,11 @@ protected: // may not be a humongous - it must fit into a single heap region. HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size); + HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose, + HeapRegion* alloc_region, + bool par, + size_t word_size); + // Ensure that no further allocations can happen in "r", bearing in mind // that parallel threads might be attempting allocations. void par_allocate_remaining_space(HeapRegion* r); @@ -1771,95 +1776,6 @@ public: ParGCAllocBuffer::retire(end_of_gc, retain); _retired = true; } - - bool is_retired() { - return _retired; - } -}; - -class G1ParGCAllocBufferContainer { -protected: - static int const _priority_max = 2; - G1ParGCAllocBuffer* _priority_buffer[_priority_max]; - -public: - G1ParGCAllocBufferContainer(size_t gclab_word_size) { - for (int pr = 0; pr < _priority_max; ++pr) { - _priority_buffer[pr] = new G1ParGCAllocBuffer(gclab_word_size); - } - } - - ~G1ParGCAllocBufferContainer() { - for (int pr = 0; pr < _priority_max; ++pr) { - assert(_priority_buffer[pr]->is_retired(), "alloc buffers should all retire at this point."); - delete _priority_buffer[pr]; - } - } - - HeapWord* allocate(size_t word_sz) { - HeapWord* obj; - for (int pr = 0; pr < _priority_max; ++pr) { - obj = _priority_buffer[pr]->allocate(word_sz); - if (obj != NULL) return obj; - } - return obj; - } - - bool contains(void* addr) { - for (int pr = 0; pr < _priority_max; ++pr) { - if (_priority_buffer[pr]->contains(addr)) return true; - } - return false; - } - - void undo_allocation(HeapWord* obj, size_t word_sz) { - bool finish_undo; - for (int pr = 0; pr < _priority_max; ++pr) { - if (_priority_buffer[pr]->contains(obj)) { - _priority_buffer[pr]->undo_allocation(obj, word_sz); - finish_undo = true; - } - } - if (!finish_undo) ShouldNotReachHere(); - } - - size_t words_remaining() { - size_t result = 0; - for (int pr = 0; pr < _priority_max; ++pr) { - result += _priority_buffer[pr]->words_remaining(); - } - return result; - } - - size_t words_remaining_in_retired_buffer() { - G1ParGCAllocBuffer* retired = _priority_buffer[0]; - return retired->words_remaining(); - } - - void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) { - for (int pr = 0; pr < _priority_max; ++pr) { - _priority_buffer[pr]->flush_stats_and_retire(stats, end_of_gc, retain); - } - } - - void update(bool end_of_gc, bool retain, HeapWord* buf, size_t word_sz) { - G1ParGCAllocBuffer* retired_and_set = _priority_buffer[0]; - retired_and_set->retire(end_of_gc, retain); - retired_and_set->set_buf(buf); - retired_and_set->set_word_size(word_sz); - adjust_priority_order(); - } - -private: - void adjust_priority_order() { - G1ParGCAllocBuffer* retired_and_set = _priority_buffer[0]; - - int last = _priority_max - 1; - for (int pr = 0; pr < last; ++pr) { - _priority_buffer[pr] = _priority_buffer[pr + 1]; - } - _priority_buffer[last] = retired_and_set; - } }; class G1ParScanThreadState : public StackObj { @@ -1870,9 +1786,9 @@ protected: G1SATBCardTableModRefBS* _ct_bs; G1RemSet* _g1_rem; - G1ParGCAllocBufferContainer _surviving_alloc_buffer; - G1ParGCAllocBufferContainer _tenured_alloc_buffer; - G1ParGCAllocBufferContainer* _alloc_buffers[GCAllocPurposeCount]; + G1ParGCAllocBuffer _surviving_alloc_buffer; + G1ParGCAllocBuffer _tenured_alloc_buffer; + G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount]; ageTable _age_table; G1ParScanClosure _scanner; @@ -1938,7 +1854,7 @@ public: RefToScanQueue* refs() { return _refs; } ageTable* age_table() { return &_age_table; } - G1ParGCAllocBufferContainer* alloc_buffer(GCAllocPurpose purpose) { + G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { return _alloc_buffers[purpose]; } @@ -1968,13 +1884,15 @@ public: HeapWord* obj = NULL; size_t gclab_word_size = _g1h->desired_plab_sz(purpose); if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { - G1ParGCAllocBufferContainer* alloc_buf = alloc_buffer(purpose); + G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); + add_to_alloc_buffer_waste(alloc_buf->words_remaining()); + alloc_buf->retire(false /* end_of_gc */, false /* retain */); HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size); if (buf == NULL) return NULL; // Let caller handle allocation failure. - - add_to_alloc_buffer_waste(alloc_buf->words_remaining_in_retired_buffer()); - alloc_buf->update(false /* end_of_gc */, false /* retain */, buf, gclab_word_size); + // Otherwise. + alloc_buf->set_word_size(gclab_word_size); + alloc_buf->set_buf(buf); obj = alloc_buf->allocate(word_sz); assert(obj != NULL, "buffer was definitely big enough..."); @@ -2088,6 +2006,7 @@ public: } } +public: void trim_queue(); }; diff --git a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp index f1c0fbf64fe..2eecbed31fc 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp @@ -158,7 +158,7 @@ public: // Fills in the unallocated portion of the buffer with a garbage object. // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" // is true, attempt to re-use the unused portion in the next GC. - virtual void retire(bool end_of_gc, bool retain); + void retire(bool end_of_gc, bool retain); void print() PRODUCT_RETURN; }; From 0bedc5f1e7295d38b8c315410d7da4bfa1914428 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 24 Feb 2014 12:16:58 +0100 Subject: [PATCH 185/265] 8034788: Rewrite toolchain.m4 to support multiple toolchains per platform Reviewed-by: henryjen, erikj --- common/autoconf/basics.m4 | 2 +- common/autoconf/build-performance.m4 | 2 +- common/autoconf/configure | 7 + common/autoconf/configure.ac | 48 +- common/autoconf/flags.m4 | 699 ++ common/autoconf/generated-configure.sh | 11769 +++++++++++------------ common/autoconf/help.m4 | 28 +- common/autoconf/hotspot-spec.gmk.in | 2 + common/autoconf/jdk-options.m4 | 2 - common/autoconf/libraries.m4 | 17 +- common/autoconf/spec.gmk.in | 7 +- common/autoconf/toolchain.m4 | 1462 +-- make/Main.gmk | 2 +- make/common/NativeCompilation.gmk | 14 +- 14 files changed, 7152 insertions(+), 6909 deletions(-) create mode 100644 common/autoconf/flags.m4 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index cc17ae0041e..16e33447c3f 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -126,7 +126,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE], done IFS="$IFS_save" else - AC_MSG_NOTICE([Resolving $1 (as $path) failed, using $path directly.]) + # This is an absolute path, we can use it without further modifications. new_path="$path" fi diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index 1bf5628485c..500c3adb702 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -261,7 +261,7 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS], if test "x$ENABLE_PRECOMPH" = xyes; then # Check that the compiler actually supports precomp headers. - if test "x$GCC" = xyes; then + if test "x$TOOLCHAIN_TYPE" = xgcc; then AC_MSG_CHECKING([that precompiled headers work]) echo "int alfa();" > conftest.h $CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD diff --git a/common/autoconf/configure b/common/autoconf/configure index 2c9cd7293b9..1376f48874a 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -263,6 +263,13 @@ Additional (non-autoconf) OpenJDK Options: --debug-configure Run the configure script with additional debug logging enabled. +EOT + + # Print list of toolchains. This must be done by the autoconf script. + ( CONFIGURE_PRINT_TOOLCHAIN_LIST=true . $conf_script_to_run PRINTF=printf ) + + cat < if you have libraries in a @@ -2016,19 +2014,22 @@ Some influential environment variables: you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags - OBJC Objective C compiler command - OBJCFLAGS Objective C compiler flags - AR Override default value for AR CPP C preprocessor CXXCPP C++ preprocessor AS Override default value for AS + AR Override default value for AR + OBJC Objective C compiler command + OBJCFLAGS Objective C compiler flags + LIPO Override default value for LIPO + STRIP Override default value for STRIP NM Override default value for NM GNM Override default value for GNM - STRIP Override default value for STRIP MCS Override default value for MCS OBJCOPY Override default value for OBJCOPY OBJDUMP Override default value for OBJDUMP - LIPO Override default value for LIPO + BUILD_CC Override default value for BUILD_CC + BUILD_CXX Override default value for BUILD_CXX + BUILD_LD Override default value for BUILD_LD JTREGEXE Override default value for JTREGEXE XMKMF Path to xmkmf, Makefile generator for X Window System FREETYPE_CFLAGS @@ -2199,44 +2200,6 @@ fi } # ac_fn_cxx_try_compile -# ac_fn_objc_try_compile LINENO -# ----------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_objc_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_objc_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_objc_try_compile - # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. @@ -2311,6 +2274,44 @@ fi } # ac_fn_cxx_try_cpp +# ac_fn_objc_try_compile LINENO +# ----------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_objc_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_objc_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_objc_try_compile + # ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using @@ -3658,7 +3659,80 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + + + + + +# Documentation on common flags used for solstudio in HIGHEST. +# +# WARNING: Use of OPTIMIZATION_LEVEL=HIGHEST in your Makefile needs to be +# done with care, there are some assumptions below that need to +# be understood about the use of pointers, and IEEE behavior. +# +# -fns: Use non-standard floating point mode (not IEEE 754) +# -fsimple: Do some simplification of floating point arithmetic (not IEEE 754) +# -fsingle: Use single precision floating point with 'float' +# -xalias_level=basic: Assume memory references via basic pointer types do not alias +# (Source with excessing pointer casting and data access with mixed +# pointer types are not recommended) +# -xbuiltin=%all: Use intrinsic or inline versions for math/std functions +# (If you expect perfect errno behavior, do not use this) +# -xdepend: Loop data dependency optimizations (need -xO3 or higher) +# -xrestrict: Pointer parameters to functions do not overlap +# (Similar to -xalias_level=basic usage, but less obvious sometimes. +# If you pass in multiple pointers to the same data, do not use this) +# -xlibmil: Inline some library routines +# (If you expect perfect errno behavior, do not use this) +# -xlibmopt: Use optimized math routines (CURRENTLY DISABLED) +# (If you expect perfect errno behavior, do not use this) +# Can cause undefined external on Solaris 8 X86 on __sincos, removing for now + + # FIXME: this will never happen since sparc != sparcv9, ie 32 bit, which we don't build anymore. + # Bug? + #if test "x$OPENJDK_TARGET_CPU" = xsparc; then + # CFLAGS_JDK="${CFLAGS_JDK} -xmemalign=4s" + # CXXFLAGS_JDK="${CXXFLAGS_JDK} -xmemalign=4s" + #fi + + + + + + +# FLAGS_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE], +# [RUN-IF-FALSE]) +# ------------------------------------------------------------ +# Check that the c and c++ compilers support an argument + + + + +# +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -3777,6 +3851,12 @@ pkgadd_help() { PKGHANDLER_COMMAND="" } +# This function will check if we're called from the "configure" wrapper while +# printing --help. If so, we will print out additional information that can +# only be extracted within the autoconf script, and then exit. This must be +# called at the very beginning in configure.ac. + + # @@ -3832,7 +3912,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -3872,6 +3952,8 @@ pkgadd_help() { + + # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -3972,7 +4054,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -3996,38 +4078,90 @@ pkgadd_help() { # questions. # +######################################################################## +# This file is responsible for detecting, verifying and setting up the +# toolchain, i.e. the compiler, linker and related utilities. It will setup +# proper paths to the binaries, but it will not setup any flags. +# +# The binaries used is determined by the toolchain type, which is the family of +# compilers and related tools that are used. +######################################################################## + + +# All valid toolchains, regardless of platform (used by help.m4) +VALID_TOOLCHAINS_all="gcc clang solstudio xlc microsoft" + +# These toolchains are valid on different platforms +VALID_TOOLCHAINS_linux="gcc clang" +VALID_TOOLCHAINS_solaris="solstudio" +VALID_TOOLCHAINS_macosx="gcc clang" +VALID_TOOLCHAINS_aix="xlc" +VALID_TOOLCHAINS_windows="microsoft" + +# Toolchain descriptions +TOOLCHAIN_DESCRIPTION_clang="clang/LLVM" +TOOLCHAIN_DESCRIPTION_gcc="GNU Compiler Collection" +TOOLCHAIN_DESCRIPTION_microsoft="Microsoft Visual Studio" +TOOLCHAIN_DESCRIPTION_solstudio="Oracle Solaris Studio" +TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" + +# Setup a number of variables describing how native output files are +# named on this platform/toolchain. + + +# Determine which toolchain type to use, and make sure it is valid for this +# platform. Setup various information about the selected toolchain. + + +# Before we start detecting the toolchain executables, we might need some +# special setup, e.g. additional paths etc. + + +# Restore path, etc + + +# Check if a compiler is of the toolchain type we expect, and save the version +# information from it. If the compiler does not match the expected type, +# this function will abort using AC_MSG_ERROR. If it matches, the version will +# be stored in CC_VERSION_NUMBER/CXX_VERSION_NUMBER (as a dotted number), and +# the full version string in CC_VERSION_STRING/CXX_VERSION_STRING. +# # $1 = compiler to test (CC or CXX) # $2 = human readable name of compiler (C or C++) - - - +# Try to locate the given C or C++ compiler in the path, or otherwise. +# # $1 = compiler to test (CC or CXX) # $2 = human readable name of compiler (C or C++) # $3 = list of compiler names to search for +# Detect the core components of the toolchain, i.e. the compilers (CC and CXX), +# preprocessor (CPP and CXXCPP), the linker (LD), the assembler (AS) and the +# archiver (AR). Verify that the compilers are correct according to the +# toolchain type. +# Setup additional tools that is considered a part of the toolchain, but not the +# core part. Many of these are highly platform-specific and do not exist, +# and/or are not needed on all platforms. +# Setup the build tools (i.e, the compiler and linker used to build programs +# that should be run on the build platform, not the target platform, as a build +# helper). Since the non-cross-compile case uses the normal, target compilers +# for this, we can only do this after these have been setup. +# Setup legacy variables that are still needed as alternative ways to refer to +# parts of the toolchain. +# Do some additional checks on the detected tools. - -# TOOLCHAIN_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE], -# [RUN-IF-FALSE]) -# ------------------------------------------------------------ -# Check that the c and c++ compilers support an argument - - - - -# Setup the JTREG paths +# Setup the JTReg Regression Test Harness. # @@ -4080,7 +4214,7 @@ pkgadd_help() { #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1392662653 +DATE_WHEN_GENERATED=1393240361 ############################################################################### # @@ -4091,7 +4225,25 @@ DATE_WHEN_GENERATED=1392662653 # ############################################################################### -# Basic initialization that must happen first of all +# If we are requested to print additional help, do that and then exit. +# This must be the very first call. + + if test "x$CONFIGURE_PRINT_TOOLCHAIN_LIST" != x; then + $PRINTF "The following toolchains are available as arguments to --with-toolchain-type.\n" + $PRINTF "Which are valid to use depends on the build platform.\n" + for toolchain in $VALID_TOOLCHAINS_all; do + # Use indirect variable referencing + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" + done + + # And now exit directly + exit 0 + fi + + +# Basic initialization that must happen first of all in the normal process. # Save the original command line. This is passed to us by the wrapper configure script. @@ -15153,8 +15305,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -15510,8 +15661,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -15864,8 +16014,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -16223,8 +16372,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -16576,8 +16724,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -26104,16 +26251,118 @@ $as_echo "yes from $HOTSPOT_DIST" >&6; } ############################################################################### # -# Setup the toolchain (compilers etc), i.e. the tools that need to be -# cross-compilation aware. +# Setup the toolchain (compilers etc), i.e. tools used to compile and process +# native code. # ############################################################################### +# First determine the toolchain type (compiler family) - ############################################################################### - # - # Configure the development tool paths and potential sysroot. - # + +# Check whether --with-toolchain-type was given. +if test "${with_toolchain_type+set}" = set; then : + withval=$with_toolchain_type; +fi + + + # Use indirect variable referencing + toolchain_var_name=VALID_TOOLCHAINS_$OPENJDK_BUILD_OS + VALID_TOOLCHAINS=${!toolchain_var_name} + # First toolchain type in the list is the default + DEFAULT_TOOLCHAIN=${VALID_TOOLCHAINS%% *} + + if test "x$with_toolchain_type" = xlist; then + # List all toolchains + { $as_echo "$as_me:${as_lineno-$LINENO}: The following toolchains are valid on this platform:" >&5 +$as_echo "$as_me: The following toolchains are valid on this platform:" >&6;} + for toolchain in $VALID_TOOLCHAINS; do + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" + done + + exit 0 + elif test "x$with_toolchain_type" != x; then + # User override; check that it is valid + if test "x${VALID_TOOLCHAINS/$with_toolchain_type/}" = "x${VALID_TOOLCHAINS}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Toolchain type $with_toolchain_type is not valid on this platform." >&5 +$as_echo "$as_me: Toolchain type $with_toolchain_type is not valid on this platform." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Valid toolchains: $VALID_TOOLCHAINS." >&5 +$as_echo "$as_me: Valid toolchains: $VALID_TOOLCHAINS." >&6;} + as_fn_error $? "Cannot continue." "$LINENO" 5 + fi + TOOLCHAIN_TYPE=$with_toolchain_type + else + # No flag given, use default + TOOLCHAIN_TYPE=$DEFAULT_TOOLCHAIN + fi + + + TOOLCHAIN_CC_BINARY_clang="clang" + TOOLCHAIN_CC_BINARY_gcc="gcc" + TOOLCHAIN_CC_BINARY_microsoft="cl" + TOOLCHAIN_CC_BINARY_solstudio="cc" + TOOLCHAIN_CC_BINARY_xlc="xlc_r" + + TOOLCHAIN_CXX_BINARY_clang="clang++" + TOOLCHAIN_CXX_BINARY_gcc="g++" + TOOLCHAIN_CXX_BINARY_microsoft="cl" + TOOLCHAIN_CXX_BINARY_solstudio="CC" + TOOLCHAIN_CXX_BINARY_xlc="xlC_r" + + # Use indirect variable referencing + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$TOOLCHAIN_TYPE + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + toolchain_var_name=TOOLCHAIN_CC_BINARY_$TOOLCHAIN_TYPE + TOOLCHAIN_CC_BINARY=${!toolchain_var_name} + toolchain_var_name=TOOLCHAIN_CXX_BINARY_$TOOLCHAIN_TYPE + TOOLCHAIN_CXX_BINARY=${!toolchain_var_name} + + + # Define filename patterns + if test "x$OPENJDK_TARGET_OS" = xwindows; then + LIBRARY_PREFIX= + SHARED_LIBRARY_SUFFIX='.dll' + STATIC_LIBRARY_SUFFIX='.lib' + SHARED_LIBRARY='$1.dll' + STATIC_LIBRARY='$1.lib' + OBJ_SUFFIX='.obj' + EXE_SUFFIX='.exe' + else + LIBRARY_PREFIX=lib + SHARED_LIBRARY_SUFFIX='.so' + STATIC_LIBRARY_SUFFIX='.a' + SHARED_LIBRARY='lib$1.so' + STATIC_LIBRARY='lib$1.a' + OBJ_SUFFIX='.o' + EXE_SUFFIX='' + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + SHARED_LIBRARY='lib$1.dylib' + SHARED_LIBRARY_SUFFIX='.dylib' + fi + fi + + + + + + + + + + + if test "x$TOOLCHAIN_TYPE" = "x$DEFAULT_TOOLCHAIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Using default toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)" >&5 +$as_echo "$as_me: Using default toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)" >&6;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Using user selected toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION). Default toolchain is $DEFAULT_TOOLCHAIN." >&5 +$as_echo "$as_me: Using user selected toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION). Default toolchain is $DEFAULT_TOOLCHAIN." >&6;} + fi + + +# Then detect the actual binaries needed + + # FIXME: Is this needed? ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -26121,384 +26370,24 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - # The option used to specify the target .o,.a or .so file. - # When compiling, how to specify the to be created object file. - CC_OUT_OPTION='-o$(SPACE)' - # When linking, how to specify the to be created executable. - EXE_OUT_OPTION='-o$(SPACE)' - # When linking, how to specify the to be created dynamically linkable library. - LD_OUT_OPTION='-o$(SPACE)' - # When archiving, how to specify the to be create static archive for object files. - AR_OUT_OPTION='rcs$(SPACE)' + # Store the CFLAGS etc passed to the configure script. + ORG_CFLAGS="$CFLAGS" + ORG_CXXFLAGS="$CXXFLAGS" + ORG_OBJCFLAGS="$OBJCFLAGS" + # autoconf magic only relies on PATH, so update it if tools dir is specified + OLD_PATH="$PATH" - - - -# Locate the actual tools - - -# Check whether --with-jtreg was given. -if test "${with_jtreg+set}" = set; then : - withval=$with_jtreg; -else - with_jtreg=no -fi - - - if test "x$with_jtreg" = xno; then - # jtreg disabled - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5 -$as_echo_n "checking for jtreg... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - else - if test "x$with_jtreg" != xyes; then - # with path specified. - JT_HOME="$with_jtreg" - fi - - if test "x$JT_HOME" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5 -$as_echo_n "checking for jtreg... " >&6; } - - # use JT_HOME enviroment var. - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # Input might be given as Windows format, start by converting to - # unix format. - path="$JT_HOME" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of JT_HOME" "$LINENO" 5 + # For solaris we really need solaris tools, and not the GNU equivalent. + # The build tools on Solaris reside in /usr/ccs (C Compilation System), + # so add that to path before starting to probe. + # FIXME: This was originally only done for AS,NM,GNM,STRIP,MCS,OBJCOPY,OBJDUMP. + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + PATH="/usr/ccs/bin:$PATH" fi - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - JT_HOME="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$JT_HOME" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - JT_HOME="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$JT_HOME" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of JT_HOME, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - JT_HOME="`cd "$path"; $THEPWDCMD -L`" - fi - - - # jtreg win32 script works for everybody - JTREGEXE="$JT_HOME/win32/bin/jtreg" - - if test ! -f "$JTREGEXE"; then - as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5 - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 -$as_echo "$JTREGEXE" >&6; } - else - # try to find jtreg on path - - - - # Publish this variable in the help. - - - if test "x$JTREGEXE" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in jtreg -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_JTREGEXE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $JTREGEXE in - [\\/]* | ?:[\\/]*) - ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -JTREGEXE=$ac_cv_path_JTREGEXE -if test -n "$JTREGEXE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 -$as_echo "$JTREGEXE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$JTREGEXE" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !JTREGEXE! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!JTREGEXE!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xJTREGEXE" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of JTREGEXE from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of JTREGEXE from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in jtreg -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_JTREGEXE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $JTREGEXE in - [\\/]* | ?:[\\/]*) - ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -JTREGEXE=$ac_cv_path_JTREGEXE -if test -n "$JTREGEXE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 -$as_echo "$JTREGEXE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$JTREGEXE" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$JTREGEXE" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool JTREGEXE=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool JTREGEXE=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_JTREGEXE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $JTREGEXE in - [\\/]* | ?:[\\/]*) - ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -JTREGEXE=$ac_cv_path_JTREGEXE -if test -n "$JTREGEXE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 -$as_echo "$JTREGEXE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$JTREGEXE" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool JTREGEXE=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool JTREGEXE=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JTREGEXE" >&5 -$as_echo_n "checking for JTREGEXE... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool JTREGEXE=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$JTREGEXE" = x; then - as_fn_error $? "Could not find required tool for JTREGEXE" "$LINENO" 5 - fi - - - JT_HOME="`$DIRNAME $JTREGEXE`" - fi - fi - - - - - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + # On Windows, we need to detect the visual studio installation first. + if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then # Store path to cygwin link.exe to help excluding it when searching for # VS linker. This must be done before changing the PATH when looking for VS. @@ -27170,8 +27059,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving VS_ENV_CMD (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving VS_ENV_CMD (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -27307,1835 +27195,14 @@ $as_echo "$as_me: or run \"bash.exe -l\" from a VS command prompt and then run c as_fn_error $? "Cannot continue" "$LINENO" 5 fi - - -# Check whether --with-msvcr-dll was given. -if test "${with_msvcr_dll+set}" = set; then : - withval=$with_msvcr_dll; -fi - - - if test "x$with_msvcr_dll" != x; then - # If given explicitely by user, do not probe. If not present, fail directly. - - POSSIBLE_MSVCR_DLL="$with_msvcr_dll" - METHOD="--with-msvcr-dll" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - if test "x$MSVCR_DLL" = x; then - as_fn_error $? "Could not find a proper msvcr100.dll as specified by --with-msvcr-dll" "$LINENO" 5 - fi - fi - - if test "x$MSVCR_DLL" = x; then - # Probe: Using well-known location from Visual Studio 10.0 - if test "x$VCINSTALLDIR" != x; then - CYGWIN_VC_INSTALL_DIR="$VCINSTALLDIR" - - windows_path="$CYGWIN_VC_INSTALL_DIR" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - CYGWIN_VC_INSTALL_DIR="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - CYGWIN_VC_INSTALL_DIR="$unix_path" - fi - - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - POSSIBLE_MSVCR_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x64/Microsoft.VC100.CRT/msvcr100.dll" - else - POSSIBLE_MSVCR_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x86/Microsoft.VC100.CRT/msvcr100.dll" - fi - - POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - METHOD="well-known location in VCINSTALLDIR" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - fi - fi - - if test "x$MSVCR_DLL" = x; then - # Probe: Check in the Boot JDK directory. - POSSIBLE_MSVCR_DLL="$BOOT_JDK/bin/msvcr100.dll" - - POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - METHOD="well-known location in Boot JDK" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - fi - - if test "x$MSVCR_DLL" = x; then - # Probe: Look in the Windows system32 directory - CYGWIN_SYSTEMROOT="$SYSTEMROOT" - - windows_path="$CYGWIN_SYSTEMROOT" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - CYGWIN_SYSTEMROOT="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - CYGWIN_SYSTEMROOT="$unix_path" - fi - - POSSIBLE_MSVCR_DLL="$CYGWIN_SYSTEMROOT/system32/msvcr100.dll" - - POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - METHOD="well-known location in SYSTEMROOT" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - fi - - if test "x$MSVCR_DLL" = x; then - # Probe: If Visual Studio Express is installed, there is usually one with the debugger - if test "x$VS100COMNTOOLS" != x; then - CYGWIN_VS_TOOLS_DIR="$VS100COMNTOOLS/.." - - windows_path="$CYGWIN_VS_TOOLS_DIR" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - CYGWIN_VS_TOOLS_DIR="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - CYGWIN_VS_TOOLS_DIR="$unix_path" - fi - - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VS_TOOLS_DIR" -name msvcr100.dll | $GREP -i /x64/ | $HEAD --lines 1` - else - POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VS_TOOLS_DIR" -name msvcr100.dll | $GREP -i /x86/ | $HEAD --lines 1` - fi - - POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - METHOD="search of VS100COMNTOOLS" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - fi - fi - - if test "x$MSVCR_DLL" = x; then - # Probe: Search wildly in the VCINSTALLDIR. We've probably lost by now. - # (This was the original behaviour; kept since it might turn up something) - if test "x$CYGWIN_VC_INSTALL_DIR" != x; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $GREP x64 | $HEAD --lines 1` - else - POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $GREP x86 | $GREP -v ia64 | $GREP -v x64 | $HEAD --lines 1` - if test "x$POSSIBLE_MSVCR_DLL" = x; then - # We're grasping at straws now... - POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $HEAD --lines 1` - fi - fi - - - POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - METHOD="search of VCINSTALLDIR" - if test -e "$POSSIBLE_MSVCR_DLL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 -$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} - - # Need to check if the found msvcr is correct architecture - { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 -$as_echo_n "checking found msvcr100.dll architecture... " >&6; } - MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } - MSVCR_DLL="$POSSIBLE_MSVCR_DLL" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 -$as_echo "$MSVCR_DLL" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 -$as_echo "incorrect, ignoring" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 -$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} - fi - fi - - fi - fi - - if test "x$MSVCR_DLL" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 -$as_echo_n "checking for msvcr100.dll... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - as_fn_error $? "Could not find msvcr100.dll. Please specify using --with-msvcr-dll." "$LINENO" 5 - fi - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # Input might be given as Windows format, start by converting to - # unix format. - path="$MSVCR_DLL" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of MSVCR_DLL" "$LINENO" 5 - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - MSVCR_DLL="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MSVCR_DLL to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting MSVCR_DLL to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$MSVCR_DLL" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - MSVCR_DLL="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MSVCR_DLL to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting MSVCR_DLL to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$MSVCR_DLL" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of MSVCR_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - MSVCR_DLL="`cd "$path"; $THEPWDCMD -L`" - fi - - - - -# Check whether --with-dxsdk was given. -if test "${with_dxsdk+set}" = set; then : - withval=$with_dxsdk; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&5 -$as_echo "$as_me: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&2;} -fi - - - - -# Check whether --with-dxsdk-lib was given. -if test "${with_dxsdk_lib+set}" = set; then : - withval=$with_dxsdk_lib; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&5 -$as_echo "$as_me: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&2;} -fi - - - - -# Check whether --with-dxsdk-include was given. -if test "${with_dxsdk_include+set}" = set; then : - withval=$with_dxsdk_include; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&5 -$as_echo "$as_me: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&2;} -fi - - - fi - - - - # If --build AND --host is set, then the configure script will find any - # cross compilation tools in the PATH. Cross compilation tools - # follows the cross compilation standard where they are prefixed with ${host}. - # For example the binary i686-sun-solaris2.10-gcc - # will cross compile for i686-sun-solaris2.10 - # If neither of build and host is not set, then build=host and the - # default compiler found in the path will be used. - # Setting only --host, does not seem to be really supported. - # Please set both --build and --host if you want to cross compile. - - if test "x$COMPILE_TYPE" = "xcross"; then - # Now we to find a C/C++ compiler that can build executables for the build - # platform. We can't use the AC_PROG_CC macro, since it can only be used - # once. Also, we need to do this before adding a tools dir to the path, - # otherwise we might pick up cross-compilers which don't use standard naming. - # Otherwise, we'll set the BUILD_tools to the native tools, but that'll have - # to wait until they are properly discovered. - - - # Publish this variable in the help. - - - if test "x$BUILD_CC" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in cl cc gcc -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CC in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CC=$ac_cv_path_BUILD_CC -if test -n "$BUILD_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 -$as_echo "$BUILD_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_CC" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !BUILD_CC! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_CC!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xBUILD_CC" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_CC from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of BUILD_CC from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in cl cc gcc -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CC in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CC=$ac_cv_path_BUILD_CC -if test -n "$BUILD_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 -$as_echo "$BUILD_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_CC" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$BUILD_CC" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_CC=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool BUILD_CC=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CC in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CC=$ac_cv_path_BUILD_CC -if test -n "$BUILD_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 -$as_echo "$BUILD_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$BUILD_CC" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_CC=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool BUILD_CC=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_CC" >&5 -$as_echo_n "checking for BUILD_CC... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool BUILD_CC=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CC (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_CC (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - BUILD_CC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CC to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting BUILD_CC to \"$new_complete\"" >&6;} - fi - - - - # Publish this variable in the help. - - - if test "x$BUILD_CXX" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in cl CC g++ -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CXX=$ac_cv_path_BUILD_CXX -if test -n "$BUILD_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 -$as_echo "$BUILD_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_CXX" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !BUILD_CXX! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_CXX!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xBUILD_CXX" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_CXX from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of BUILD_CXX from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in cl CC g++ -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CXX=$ac_cv_path_BUILD_CXX -if test -n "$BUILD_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 -$as_echo "$BUILD_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_CXX" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$BUILD_CXX" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_CXX=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool BUILD_CXX=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_CXX=$ac_cv_path_BUILD_CXX -if test -n "$BUILD_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 -$as_echo "$BUILD_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$BUILD_CXX" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_CXX=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool BUILD_CXX=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_CXX" >&5 -$as_echo_n "checking for BUILD_CXX... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool BUILD_CXX=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CXX (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_CXX (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" + # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to + # override all other locations. + if test "x$TOOLS_DIR" != x; then + PATH=$TOOLS_DIR:$PATH fi - if test "x$complete" != "x$new_complete"; then - BUILD_CXX="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CXX to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting BUILD_CXX to \"$new_complete\"" >&6;} - fi - - - - # Publish this variable in the help. - - - if test "x$BUILD_LD" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in ld -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_LD in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_LD=$ac_cv_path_BUILD_LD -if test -n "$BUILD_LD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 -$as_echo "$BUILD_LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_LD" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !BUILD_LD! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_LD!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xBUILD_LD" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_LD from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of BUILD_LD from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in ld -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_LD in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_LD=$ac_cv_path_BUILD_LD -if test -n "$BUILD_LD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 -$as_echo "$BUILD_LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$BUILD_LD" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$BUILD_LD" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_LD=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool BUILD_LD=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_BUILD_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $BUILD_LD in - [\\/]* | ?:[\\/]*) - ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -BUILD_LD=$ac_cv_path_BUILD_LD -if test -n "$BUILD_LD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 -$as_echo "$BUILD_LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$BUILD_LD" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_LD=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool BUILD_LD=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_LD" >&5 -$as_echo_n "checking for BUILD_LD... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool BUILD_LD=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_LD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_LD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$BUILD_LD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_LD (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_LD (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - BUILD_LD="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_LD to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting BUILD_LD to \"$new_complete\"" >&6;} - fi - - fi - - - - # If a devkit is found on the builddeps server, then prepend its path to the # PATH variable. If there are cross compilers available in the devkit, these # will be found by AC_PROG_CC et al. @@ -29294,38 +27361,13 @@ $as_echo "$as_me: Downloading build dependency devkit from $with_builddeps_serve fi - # Store the CFLAGS etal passed to the configure script. - ORG_CFLAGS="$CFLAGS" - ORG_CXXFLAGS="$CXXFLAGS" - ORG_OBJCFLAGS="$OBJCFLAGS" - - # autoconf magic only relies on PATH, so update it if tools dir is specified - OLD_PATH="$PATH" - if test "x$TOOLS_DIR" != x; then - PATH=$TOOLS_DIR:$PATH - fi - - - ### Locate C compiler (CC) - - # On windows, only cl.exe is supported. - # On Solaris, cc is preferred to gcc. - # Elsewhere, gcc is preferred to cc. - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - COMPILER_CHECK_LIST="cl" - elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - COMPILER_CHECK_LIST="cc gcc" - elif test "x$OPENJDK_TARGET_OS" = "xaix"; then - # Do not probe for cc on AIX. - COMPILER_CHECK_LIST="xlc_r" - else - COMPILER_CHECK_LIST="gcc cc" - fi + # + # Setup the compilers (CC and CXX) + # COMPILER_NAME=C - SEARCH_LIST="$COMPILER_CHECK_LIST" + SEARCH_LIST="$TOOLCHAIN_CC_BINARY" if test "x$CC" != x; then # User has supplied compiler name already, always let that override. @@ -29391,10 +27433,20 @@ done fi fi else - # No user supplied value. Locate compiler ourselves + # No user supplied value. Locate compiler ourselves. + + # If we are cross compiling, assume cross compilation tools follows the + # cross compilation standard where they are prefixed with the autoconf + # standard name for the target. For example the binary + # i686-sun-solaris2.10-gcc will cross compile for i686-sun-solaris2.10. + # If we are not cross compiling, then the default compiler name will be + # used. + CC= # If TOOLS_DIR is set, check for all compiler names in there first # before checking the rest of the PATH. + # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION + # step, this should not be necessary. if test -n "$TOOLS_DIR"; then PATH_save="$PATH" PATH="$TOOLS_DIR" @@ -29770,8 +27822,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CC (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CC (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -29804,6 +27855,7 @@ $as_echo "$as_me: Rewriting CC to \"$new_complete\"" >&6;} # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links # to 'xlc' but it is crucial that we invoke the compiler with the right name! if test "x$OPENJDK_BUILD_OS" != xaix; then + # FIXME: This test should not be needed anymore; we don't do that for any platform. { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CC" >&5 $as_echo_n "checking resolved symbolic links for CC... " >&6; } @@ -29875,7 +27927,7 @@ $as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } # Try again looking for our compiler if test -n "$ac_tool_prefix"; then - for ac_prog in $COMPILER_CHECK_LIST + for ac_prog in $TOOLCHAIN_CC_BINARY do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -29919,7 +27971,7 @@ fi fi if test -z "$PROPER_COMPILER_CC"; then ac_ct_PROPER_COMPILER_CC=$PROPER_COMPILER_CC - for ac_prog in $COMPILER_CHECK_LIST + for ac_prog in $TOOLCHAIN_CC_BINARY do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -30210,8 +28262,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CC (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving PROPER_COMPILER_CC (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -30304,71 +28355,121 @@ $as_echo "no, keeping CC" >&6; } COMPILER=$CC COMPILER_NAME=$COMPILER_NAME - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - # Make sure we use the Sun Studio compiler and not gcc on Solaris, which won't work - COMPILER_VERSION_TEST=`$COMPILER -V 2>&1 | $HEAD -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + # cc -V output typically looks like + # cc: Sun C 5.12 Linux_i386 2011/11/16 + COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1` + # Check that this is likely to be the Solaris Studio cc. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null if test $? -ne 0; then - GCC_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - - { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler." >&5 -$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_TEST\" and with --version: \"$GCC_VERSION_TEST\"" >&5 -$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_TEST\" and with --version: \"$GCC_VERSION_TEST\"" >&6;} - as_fn_error $? "Sun Studio compiler is required. Try setting --with-tools-dir." "$LINENO" 5 - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/p"` - COMPILER_VENDOR="Sun Studio" + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 fi - elif test "x$OPENJDK_TARGET_OS" = xaix; then - COMPILER_VERSION_TEST=`$COMPILER -qversion 2>&1 | $TAIL -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^Version: " > /dev/null - if test $? -ne 0; then - as_fn_error $? "Failed to detect the compiler version of $COMPILER ...." "$LINENO" 5 - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n 's/Version: \(0-90-9\.0-90-9*\).*/\1/p'` - COMPILER_VENDOR='IBM' - fi - elif test "x$OPENJDK_TARGET_OS" = xwindows; then + # Remove usage instructions (if present), and + # collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *[Uu]sage:.*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/"` + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + # xlc -qversion output typically looks like + # IBM XL C/C++ for AIX, V11.1 (5724-X13) + # Version: 11.01.0000.0015 + COMPILER_VERSION_OUTPUT=`$COMPILER -qversion 2>&1` + # Check that this is likely to be the IBM XL C compiler. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "IBM XL C" > /dev/null + if test $? -ne 0; then + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*, V\([1-9][0-9.]*\).*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # There is no specific version flag, but all output starts with a version string. # First line typically looks something like: # Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 - COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"` - COMPILER_VENDOR="Microsoft CL.EXE" - COMPILER_CPU_TEST=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* for \(.*\)$/\1/p"` - if test "x$OPENJDK_TARGET_CPU" = "xx86"; then - if test "x$COMPILER_CPU_TEST" != "x80x86"; then - as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"80x86\"." "$LINENO" 5 - fi - elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then - if test "x$COMPILER_CPU_TEST" != "xx64"; then - as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"x64\"." "$LINENO" 5 - fi - fi - else - COMPILER_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - # Check that this is likely to be GCC. - $COMPILER --version 2>&1 | $GREP "Free Software Foundation" > /dev/null + COMPILER_VERSION_OUTPUT=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` + # Check that this is likely to be Microsoft CL.EXE. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Microsoft.*Compiler" > /dev/null if test $? -ne 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required GCC compiler." >&5 -$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required GCC compiler." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_TEST\"" >&5 -$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_TEST\"" >&6;} - as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 fi - - # First line typically looks something like: - # gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* \([1-9][0-9.]*\)/\1/p"` - COMPILER_VENDOR=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^\(.*\) [1-9][0-9.]*/\1/p"` + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*ersion.\([1-9][0-9.]*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # gcc --version output typically looks like + # gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 + # Copyright (C) 2013 Free Software Foundation, Inc. + # This is free software; see the source for copying conditions. There is NO + # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be GCC. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Free Software Foundation" > /dev/null + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Remove Copyright and legalese from version string, and + # collapse into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *Copyright .*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.* \([1-9]\.[0-9.]*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xclang; then + # clang --version output typically looks like + # Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) + # clang version 3.3 (tags/RELEASE_33/final) + # or + # Debian clang version 3.2-7ubuntu1 (tags/RELEASE_32/final) (based on LLVM 3.2) + # Target: x86_64-pc-linux-gnu + # Thread model: posix + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be clang + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "clang" > /dev/null + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*clang version \([1-9][0-9.]*\).*$/\1/'` + else + as_fn_error $? "Unknown toolchain type $TOOLCHAIN_TYPE." "$LINENO" 5 fi - # This sets CC_VERSION or CXX_VERSION. (This comment is a grep marker) - CC_VERSION="$COMPILER_VERSION" - # This sets CC_VENDOR or CXX_VENDOR. (This comment is a grep marker) - CC_VENDOR="$COMPILER_VENDOR" + # This sets CC_VERSION_NUMBER or CXX_VERSION_NUMBER. (This comment is a grep marker) + CC_VERSION_NUMBER="$COMPILER_VERSION_NUMBER" + # This sets CC_VERSION_STRING or CXX_VERSION_STRING. (This comment is a grep marker) + CC_VERSION_STRING="$COMPILER_VERSION_STRING" - { $as_echo "$as_me:${as_lineno-$LINENO}: Using $COMPILER_VENDOR $COMPILER_NAME compiler version $COMPILER_VERSION (located at $COMPILER)" >&5 -$as_echo "$as_me: Using $COMPILER_VENDOR $COMPILER_NAME compiler version $COMPILER_VERSION (located at $COMPILER)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&5 +$as_echo "$as_me: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&6;} # Now that we have resolved CC ourself, let autoconf have its go at it @@ -30970,30 +29071,9 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - # Option used to tell the compiler whether to create 32- or 64-bit executables - # Notice that CC contains the full compiler path at this point. - case $CC in - *xlc_r) COMPILER_TARGET_BITS_FLAG="-q";; - *) COMPILER_TARGET_BITS_FLAG="-m";; - esac - - - ### Locate C++ compiler (CXX) - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - COMPILER_CHECK_LIST="cl" - elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - COMPILER_CHECK_LIST="CC g++" - elif test "x$OPENJDK_TARGET_OS" = "xaix"; then - # Do not probe for CC on AIX . - COMPILER_CHECK_LIST="xlC_r" - else - COMPILER_CHECK_LIST="g++ CC" - fi - COMPILER_NAME=C++ - SEARCH_LIST="$COMPILER_CHECK_LIST" + SEARCH_LIST="$TOOLCHAIN_CXX_BINARY" if test "x$CXX" != x; then # User has supplied compiler name already, always let that override. @@ -31059,10 +29139,20 @@ done fi fi else - # No user supplied value. Locate compiler ourselves + # No user supplied value. Locate compiler ourselves. + + # If we are cross compiling, assume cross compilation tools follows the + # cross compilation standard where they are prefixed with the autoconf + # standard name for the target. For example the binary + # i686-sun-solaris2.10-gcc will cross compile for i686-sun-solaris2.10. + # If we are not cross compiling, then the default compiler name will be + # used. + CXX= # If TOOLS_DIR is set, check for all compiler names in there first # before checking the rest of the PATH. + # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION + # step, this should not be necessary. if test -n "$TOOLS_DIR"; then PATH_save="$PATH" PATH="$TOOLS_DIR" @@ -31438,8 +29528,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXX (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CXX (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -31472,6 +29561,7 @@ $as_echo "$as_me: Rewriting CXX to \"$new_complete\"" >&6;} # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links # to 'xlc' but it is crucial that we invoke the compiler with the right name! if test "x$OPENJDK_BUILD_OS" != xaix; then + # FIXME: This test should not be needed anymore; we don't do that for any platform. { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CXX" >&5 $as_echo_n "checking resolved symbolic links for CXX... " >&6; } @@ -31543,7 +29633,7 @@ $as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } # Try again looking for our compiler if test -n "$ac_tool_prefix"; then - for ac_prog in $COMPILER_CHECK_LIST + for ac_prog in $TOOLCHAIN_CXX_BINARY do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -31587,7 +29677,7 @@ fi fi if test -z "$PROPER_COMPILER_CXX"; then ac_ct_PROPER_COMPILER_CXX=$PROPER_COMPILER_CXX - for ac_prog in $COMPILER_CHECK_LIST + for ac_prog in $TOOLCHAIN_CXX_BINARY do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -31878,8 +29968,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CXX (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving PROPER_COMPILER_CXX (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -31972,71 +30061,121 @@ $as_echo "no, keeping CXX" >&6; } COMPILER=$CXX COMPILER_NAME=$COMPILER_NAME - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - # Make sure we use the Sun Studio compiler and not gcc on Solaris, which won't work - COMPILER_VERSION_TEST=`$COMPILER -V 2>&1 | $HEAD -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + # cc -V output typically looks like + # cc: Sun C 5.12 Linux_i386 2011/11/16 + COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1` + # Check that this is likely to be the Solaris Studio cc. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null if test $? -ne 0; then - GCC_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - - { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler." >&5 -$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_TEST\" and with --version: \"$GCC_VERSION_TEST\"" >&5 -$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_TEST\" and with --version: \"$GCC_VERSION_TEST\"" >&6;} - as_fn_error $? "Sun Studio compiler is required. Try setting --with-tools-dir." "$LINENO" 5 - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/p"` - COMPILER_VENDOR="Sun Studio" + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 fi - elif test "x$OPENJDK_TARGET_OS" = xaix; then - COMPILER_VERSION_TEST=`$COMPILER -qversion 2>&1 | $TAIL -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^Version: " > /dev/null - if test $? -ne 0; then - as_fn_error $? "Failed to detect the compiler version of $COMPILER ...." "$LINENO" 5 - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n 's/Version: \(0-90-9\.0-90-9*\).*/\1/p'` - COMPILER_VENDOR='IBM' - fi - elif test "x$OPENJDK_TARGET_OS" = xwindows; then + # Remove usage instructions (if present), and + # collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *[Uu]sage:.*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e "s/^.*[ ,\t]$COMPILER_NAME[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/"` + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + # xlc -qversion output typically looks like + # IBM XL C/C++ for AIX, V11.1 (5724-X13) + # Version: 11.01.0000.0015 + COMPILER_VERSION_OUTPUT=`$COMPILER -qversion 2>&1` + # Check that this is likely to be the IBM XL C compiler. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "IBM XL C" > /dev/null + if test $? -ne 0; then + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with -qversion was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*, V\([1-9][0-9.]*\).*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # There is no specific version flag, but all output starts with a version string. # First line typically looks something like: # Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 - COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \([1-9][0-9.]*\) .*/\1/p"` - COMPILER_VENDOR="Microsoft CL.EXE" - COMPILER_CPU_TEST=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* for \(.*\)$/\1/p"` - if test "x$OPENJDK_TARGET_CPU" = "xx86"; then - if test "x$COMPILER_CPU_TEST" != "x80x86"; then - as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"80x86\"." "$LINENO" 5 - fi - elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then - if test "x$COMPILER_CPU_TEST" != "xx64"; then - as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"x64\"." "$LINENO" 5 - fi - fi - else - COMPILER_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - # Check that this is likely to be GCC. - $COMPILER --version 2>&1 | $GREP "Free Software Foundation" > /dev/null + COMPILER_VERSION_OUTPUT=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` + # Check that this is likely to be Microsoft CL.EXE. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Microsoft.*Compiler" > /dev/null if test $? -ne 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required GCC compiler." >&5 -$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required GCC compiler." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_TEST\"" >&5 -$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_TEST\"" >&6;} - as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 fi - - # First line typically looks something like: - # gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* \([1-9][0-9.]*\)/\1/p"` - COMPILER_VENDOR=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^\(.*\) [1-9][0-9.]*/\1/p"` + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*ersion.\([1-9][0-9.]*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # gcc --version output typically looks like + # gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 + # Copyright (C) 2013 Free Software Foundation, Inc. + # This is free software; see the source for copying conditions. There is NO + # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be GCC. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Free Software Foundation" > /dev/null + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Remove Copyright and legalese from version string, and + # collapse into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *Copyright .*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.* \([1-9]\.[0-9.]*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xclang; then + # clang --version output typically looks like + # Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) + # clang version 3.3 (tags/RELEASE_33/final) + # or + # Debian clang version 3.2-7ubuntu1 (tags/RELEASE_32/final) (based on LLVM 3.2) + # Target: x86_64-pc-linux-gnu + # Thread model: posix + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be clang + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "clang" > /dev/null + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5 +$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&5 +$as_echo "$as_me: The result from running with --version was: \"$COMPILER_VERSION_OUTPUT\"" >&6;} + as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5 + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*clang version \([1-9][0-9.]*\).*$/\1/'` + else + as_fn_error $? "Unknown toolchain type $TOOLCHAIN_TYPE." "$LINENO" 5 fi - # This sets CC_VERSION or CXX_VERSION. (This comment is a grep marker) - CXX_VERSION="$COMPILER_VERSION" - # This sets CC_VENDOR or CXX_VENDOR. (This comment is a grep marker) - CXX_VENDOR="$COMPILER_VENDOR" + # This sets CC_VERSION_NUMBER or CXX_VERSION_NUMBER. (This comment is a grep marker) + CXX_VERSION_NUMBER="$COMPILER_VERSION_NUMBER" + # This sets CC_VERSION_STRING or CXX_VERSION_STRING. (This comment is a grep marker) + CXX_VERSION_STRING="$COMPILER_VERSION_STRING" - { $as_echo "$as_me:${as_lineno-$LINENO}: Using $COMPILER_VENDOR $COMPILER_NAME compiler version $COMPILER_VERSION (located at $COMPILER)" >&5 -$as_echo "$as_me: Using $COMPILER_VENDOR $COMPILER_NAME compiler version $COMPILER_VERSION (located at $COMPILER)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&5 +$as_echo "$as_me: Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER [$COMPILER_VERSION_STRING]" >&6;} # Now that we have resolved CXX ourself, let autoconf have its go at it @@ -32298,9 +30437,2228 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - ### Locate other tools + # + # Setup the preprocessor (CPP and CXXCPP) + # + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : - if test "x$OPENJDK_TARGET_OS" = xmacosx; then +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$CPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of CPP, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$CPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$CPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + CPP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CPP to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting CPP to \"$new_complete\"" >&6;} + fi + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$CXXCPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of CXXCPP, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$CXXCPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$CXXCPP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + CXXCPP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXXCPP to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting CXXCPP to \"$new_complete\"" >&6;} + fi + + + # + # Setup the linker (LD) + # + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # In the Microsoft toolchain we have a separate LD command "link". + # Make sure we reject /usr/bin/link (as determined in CYGWIN_LINK), which is + # a cygwin program for something completely different. + # Extract the first word of "link", so it can be a program name with args. +set dummy link; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LD"; then + ac_cv_prog_LD="$LD" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "$CYGWIN_LINK"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_LD="link" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_LD + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set LD to just the basename; use the full file name. + shift + ac_cv_prog_LD="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +LD=$ac_cv_prog_LD +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of LD" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LD, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of LD, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of LD" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of LD" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of LD" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + LD="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting LD to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting LD to \"$new_complete\"" >&6;} + fi + + # Verify that we indeed succeeded with this trick. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the found link.exe is actually the Visual Studio linker" >&5 +$as_echo_n "checking if the found link.exe is actually the Visual Studio linker... " >&6; } + "$LD" --version > /dev/null + if test $? -eq 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "This is the Cygwin link tool. Please check your PATH and rerun configure." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + LDCXX="$LD" + else + # All other toolchains use the compiler to link. + LD="$CC" + LDCXX="$CXX" + fi + + # FIXME: it should be CXXLD, according to standard (cf CXXCPP) + + + # + # Setup the assembler (AS) + # + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: should this really be solaris, or solstudio? + + + # Publish this variable in the help. + + + if test "x$AS" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in as +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AS in + [\\/]* | ?:[\\/]*) + ac_cv_path_AS="$AS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AS=$ac_cv_path_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AS" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !AS! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!AS!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xAS" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of AS from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of AS from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in as +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AS in + [\\/]* | ?:[\\/]*) + ac_cv_path_AS="$AS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AS=$ac_cv_path_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AS" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$AS" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool AS=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool AS=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AS in + [\\/]* | ?:[\\/]*) + ac_cv_path_AS="$AS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AS=$ac_cv_path_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$AS" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool AS=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool AS=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AS" >&5 +$as_echo_n "checking for AS... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool AS=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$AS" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of AS, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$AS" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$AS" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + AS="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AS to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting AS to \"$new_complete\"" >&6;} + fi + + else + # FIXME: is this correct for microsoft? + AS="$CC -c" + fi + + + # + # Setup the archiver (AR) + # + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # The corresponding ar tool is lib.exe (used to create static libraries) + # Extract the first word of "lib", so it can be a program name with args. +set dummy lib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="lib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + + + # Publish this variable in the help. + + + if test "x$AR" = x; then + # The variable is not set by user, try to locate tool using the code snippet + if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !AR! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!AR!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xAR" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of AR from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of AR from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$AR" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool AR=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool AR=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AR=$ac_cv_path_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$AR" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool AR=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool AR=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AR" >&5 +$as_echo_n "checking for AR... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool AR=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + fi + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$AR" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of AR, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$AR" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$AR" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + AR="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AR to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting AR to \"$new_complete\"" >&6;} + fi + + + + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then ac_ext=m ac_cpp='$OBJCPP $CPPFLAGS' ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -32788,8 +33146,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJC (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJC (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -32818,101 +33175,35 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow $as_echo "$as_me: Rewriting OBJC to \"$new_complete\"" >&6;} fi - else - OBJC= - fi - - # Restore the flags to the user specified values. - # This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2" - CFLAGS="$ORG_CFLAGS" - CXXFLAGS="$ORG_CXXFLAGS" - OBJCFLAGS="$ORG_OBJCFLAGS" - - LD="$CC" - LDEXE="$CC" - LDCXX="$CXX" - LDEXECXX="$CXX" - - # LDEXE is the linker to use, when creating executables. - - # Linking C++ libraries. - - # Linking C++ executables. - - - if test "x$OPENJDK_TARGET_OS" != xwindows; then # Publish this variable in the help. - if test "x$AR" = x; then + if test "x$LIPO" = x; then # The variable is not set by user, try to locate tool using the code snippet - if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AR" && break - done -fi -if test -z "$AR"; then - ac_ct_AR=$AR - for ac_prog in ar + for ac_prog in lipo do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : +if ${ac_cv_path_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + case $LIPO in + [\\/]* | ?:[\\/]*) + ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" + ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -32920,112 +33211,57 @@ done done IFS=$as_save_IFS + ;; +esac fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } +LIPO=$ac_cv_path_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$ac_ct_AR" && break + test -n "$LIPO" && break done - if test "x$ac_ct_AR" = x; then - AR="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -fi - else # The variable is set, but is it from the command line or the environment? - # Try to remove the string !AR! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!AR!/} + # Try to remove the string !LIPO! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!LIPO!/} if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then # If it failed, the variable was not from the command line. Ignore it, # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xAR" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of AR from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of AR from the environment. Use command line variables instead." >&2;} + if test "xLIPO" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of LIPO from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of LIPO from the environment. Use command line variables instead." >&2;} fi # Try to locate tool using the code snippet - if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AR" && break - done -fi -if test -z "$AR"; then - ac_ct_AR=$AR - for ac_prog in ar + for ac_prog in lipo do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : +if ${ac_cv_path_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + case $LIPO in + [\\/]* | ?:[\\/]*) + ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" + ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -33033,34 +33269,22 @@ done done IFS=$as_save_IFS + ;; +esac fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } +LIPO=$ac_cv_path_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$ac_ct_AR" && break + test -n "$LIPO" && break done - if test "x$ac_ct_AR" = x; then - AR="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -fi - else # If it succeeded, then it was overridden by the user. We will use it # for the tool. @@ -33070,22 +33294,22 @@ fi CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" # Check if the provided tool contains a complete path. - tool_specified="$AR" + tool_specified="$LIPO" tool_basename="${tool_specified##*/}" if test "x$tool_basename" = "x$tool_specified"; then # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool AR=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool AR=$tool_basename" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool LIPO=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool LIPO=$tool_basename" >&6;} # Extract the first word of "$tool_basename", so it can be a program name with args. set dummy $tool_basename; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_AR+:} false; then : +if ${ac_cv_path_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else - case $AR in + case $LIPO in [\\/]* | ?:[\\/]*) - ac_cv_path_AR="$AR" # Let the user override the test with a path. + ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -33095,7 +33319,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -33106,29 +33330,29 @@ IFS=$as_save_IFS ;; esac fi -AR=$ac_cv_path_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } +LIPO=$ac_cv_path_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$AR" = x; then + if test "x$LIPO" = x; then as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 fi else # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool AR=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool AR=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AR" >&5 -$as_echo_n "checking for AR... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool LIPO=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool LIPO=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIPO" >&5 +$as_echo_n "checking for LIPO... " >&6; } if test ! -x "$tool_specified"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "User supplied tool AR=$tool_specified does not exist or is not executable" "$LINENO" 5 + as_fn_error $? "User supplied tool LIPO=$tool_specified does not exist or is not executable" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 $as_echo "$tool_specified" >&6; } @@ -33142,7 +33366,7 @@ $as_echo "$tool_specified" >&6; } # First separate the path from the arguments. This will split at the first # space. - complete="$AR" + complete="$LIPO" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -33178,14 +33402,14 @@ $as_echo "$tool_specified" >&6; } fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 fi fi @@ -33205,11 +33429,11 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh elif test -f "${new_path}.cmd"; then input_to_shortpath="${new_path}.cmd" else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of AR, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of LIPO, which resolves as \"$new_path\", is invalid." >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 fi else input_to_shortpath="$new_path" @@ -33256,7 +33480,7 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" # First separate the path from the arguments. This will split at the first # space. - complete="$AR" + complete="$LIPO" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -33301,14 +33525,14 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 fi fi @@ -33354,7 +33578,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # We're on a posix platform. Hooray! :) # First separate the path from the arguments. This will split at the first # space. - complete="$AR" + complete="$LIPO" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -33373,20 +33597,19 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AR (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving AR (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 $as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 fi fi @@ -33398,377 +33621,16 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi if test "x$complete" != "x$new_complete"; then - AR="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AR to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting AR to \"$new_complete\"" >&6;} - fi - - fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - ARFLAGS="-r" - elif test "x$OPENJDK_TARGET_OS" = xaix; then - ARFLAGS="-X64" - else - ARFLAGS="" - fi - - - # For hotspot, we need these in Windows mixed path; other platforms keep them the same - HOTSPOT_CXX="$CXX" - HOTSPOT_LD="$LD" - - - - COMPILER_NAME=gcc - COMPILER_TYPE=CC - if test "x$OPENJDK_TARGET_OS" = xwindows; then : - - # For now, assume that we are always compiling using cl.exe. - CC_OUT_OPTION=-Fo - EXE_OUT_OPTION=-out: - LD_OUT_OPTION=-out: - AR_OUT_OPTION=-out: - # On Windows, reject /usr/bin/link (as determined in CYGWIN_LINK), which is a cygwin - # program for something completely different. - # Extract the first word of "link", so it can be a program name with args. -set dummy link; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_WINLD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$WINLD"; then - ac_cv_prog_WINLD="$WINLD" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "$CYGWIN_LINK"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_WINLD="link" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_WINLD - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set WINLD to just the basename; use the full file name. - shift - ac_cv_prog_WINLD="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -WINLD=$ac_cv_prog_WINLD -if test -n "$WINLD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINLD" >&5 -$as_echo "$WINLD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - # Since we must ignore the first found link, WINLD will contain - # the full path to the link.exe program. - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINLD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINLD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINLD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINLD" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINLD, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of WINLD, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of WINLD" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINLD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINLD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINLD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINLD" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + LIPO="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting LIPO to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting LIPO to \"$new_complete\"" >&6;} fi else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINLD" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINLD (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving WINLD (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINLD, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINLD, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINLD" "$LINENO" 5 - fi + OBJC= fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - WINLD="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINLD to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting WINLD to \"$new_complete\"" >&6;} - fi - - printf "Windows linker was found at $WINLD\n" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the found link.exe is actually the Visual Studio linker" >&5 -$as_echo_n "checking if the found link.exe is actually the Visual Studio linker... " >&6; } - "$WINLD" --version > /dev/null - if test $? -eq 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - as_fn_error $? "This is the Cygwin link tool. Please check your PATH and rerun configure." "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - fi - LD="$WINLD" - LDEXE="$WINLD" - LDCXX="$WINLD" - LDEXECXX="$WINLD" - + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -34059,8 +33921,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MT (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving MT (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -34089,7 +33950,7 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow $as_echo "$as_me: Rewriting MT to \"$new_complete\"" >&6;} fi - # The resource compiler + # Setup the resource compiler (RC) # Extract the first word of "rc", so it can be a program name with args. set dummy rc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -34380,8 +34241,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving RC (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving RC (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -34410,385 +34270,7 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow $as_echo "$as_me: Rewriting RC to \"$new_complete\"" >&6;} fi - - # For hotspot, we need these in Windows mixed path, - # so rewrite them all. Need added .exe suffix. - HOTSPOT_CXX="$CXX.exe" - HOTSPOT_LD="$LD.exe" - HOTSPOT_MT="$MT.exe" - HOTSPOT_RC="$RC.exe" - - unix_path="$HOTSPOT_CXX" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - windows_path=`$CYGPATH -m "$unix_path"` - HOTSPOT_CXX="$windows_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - windows_path=`cmd //c echo $unix_path` - HOTSPOT_CXX="$windows_path" - fi - - - unix_path="$HOTSPOT_LD" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - windows_path=`$CYGPATH -m "$unix_path"` - HOTSPOT_LD="$windows_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - windows_path=`cmd //c echo $unix_path` - HOTSPOT_LD="$windows_path" - fi - - - unix_path="$HOTSPOT_MT" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - windows_path=`$CYGPATH -m "$unix_path"` - HOTSPOT_MT="$windows_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - windows_path=`cmd //c echo $unix_path` - HOTSPOT_MT="$windows_path" - fi - - - unix_path="$HOTSPOT_RC" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - windows_path=`$CYGPATH -m "$unix_path"` - HOTSPOT_RC="$windows_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - windows_path=`cmd //c echo $unix_path` - HOTSPOT_RC="$windows_path" - fi - - - - - RC_FLAGS="-nologo -l 0x409 -r" - if test "x$VARIANT" = xOPT; then : - - RC_FLAGS="$RC_FLAGS -d NDEBUG" - -fi - - # The version variables used to create RC_FLAGS may be overridden - # in a custom configure script, or possibly the command line. - # Let those variables be expanded at make time in spec.gmk. - # The \$ are escaped to the shell, and the $(...) variables - # are evaluated by make. - RC_FLAGS="$RC_FLAGS \ - -d \"JDK_BUILD_ID=\$(FULL_VERSION)\" \ - -d \"JDK_COMPANY=\$(COMPANY_NAME)\" \ - -d \"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \ - -d \"JDK_VER=\$(JDK_MINOR_VERSION).\$(JDK_MICRO_VERSION).\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0).\$(COOKED_BUILD_NUMBER)\" \ - -d \"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ - -d \"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(JDK_MINOR_VERSION) \$(JDK_UPDATE_META_TAG)\" \ - -d \"JDK_FVER=\$(JDK_MINOR_VERSION),\$(JDK_MICRO_VERSION),\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0),\$(COOKED_BUILD_NUMBER)\"" - - # lib.exe is used to create static libraries. - # Extract the first word of "lib", so it can be a program name with args. -set dummy lib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_WINAR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$WINAR"; then - ac_cv_prog_WINAR="$WINAR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_WINAR="lib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -WINAR=$ac_cv_prog_WINAR -if test -n "$WINAR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINAR" >&5 -$as_echo "$WINAR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINAR" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINAR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINAR, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINAR" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINAR, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of WINAR, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of WINAR" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINAR" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINAR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINAR, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINAR" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$WINAR" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINAR (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving WINAR (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINAR, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of WINAR, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of WINAR" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - WINAR="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINAR to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting WINAR to \"$new_complete\"" >&6;} - fi - - AR="$WINAR" - ARFLAGS="-nologo -NODEFAULTLIB:MSVCRT" - - # Extract the first word of "dumpbin", so it can be a program name with args. + # Extract the first word of "dumpbin", so it can be a program name with args. set dummy dumpbin; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } @@ -35061,8 +34543,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving DUMPBIN (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving DUMPBIN (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -35091,859 +34572,28 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow $as_echo "$as_me: Rewriting DUMPBIN to \"$new_complete\"" >&6;} fi - - COMPILER_TYPE=CL - CCXXFLAGS="$CCXXFLAGS -nologo" - -fi - - - - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$CPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 - fi fi - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of CPP, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$CPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$CPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CPP (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CPP (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - CPP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CPP to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting CPP to \"$new_complete\"" >&6;} - fi - - - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$CXXCPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of CXXCPP, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$CXXCPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$CXXCPP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXXCPP (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CXXCPP (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - CXXCPP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXXCPP to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting CXXCPP to \"$new_complete\"" >&6;} - fi - - - if test "x$COMPILE_TYPE" != "xcross"; then - # If we are not cross compiling, use the same compilers for - # building the build platform executables. The cross-compilation - # case needed to be done earlier, but this can only be done after - # the native tools have been localized. - BUILD_CC="$CC" - BUILD_CXX="$CXX" - BUILD_LD="$LD" - fi - - # for solaris we really need solaris tools, and not gnu equivalent - # these seems to normally reside in /usr/ccs/bin so add that to path before - # starting to probe - # - # NOTE: I add this /usr/ccs/bin after TOOLS but before OLD_PATH - # so that it can be overriden --with-tools-dir - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - PATH="${TOOLS_DIR}:/usr/ccs/bin:${OLD_PATH}" - fi - - # Find the right assembler. if test "x$OPENJDK_TARGET_OS" = xsolaris; then # Publish this variable in the help. - if test "x$AS" = x; then + if test "x$STRIP" = x; then # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in as + for ac_prog in strip do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_AS+:} false; then : +if ${ac_cv_path_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else - case $AS in + case $STRIP in [\\/]* | ?:[\\/]*) - ac_cv_path_AS="$AS" # Let the user override the test with a path. + ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -35953,7 +34603,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -35964,44 +34614,44 @@ IFS=$as_save_IFS ;; esac fi -AS=$ac_cv_path_AS -if test -n "$AS"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 -$as_echo "$AS" >&6; } +STRIP=$ac_cv_path_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$AS" && break + test -n "$STRIP" && break done else # The variable is set, but is it from the command line or the environment? - # Try to remove the string !AS! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!AS!/} + # Try to remove the string !STRIP! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!STRIP!/} if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then # If it failed, the variable was not from the command line. Ignore it, # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xAS" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of AS from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of AS from the environment. Use command line variables instead." >&2;} + if test "xSTRIP" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&2;} fi # Try to locate tool using the code snippet - for ac_prog in as + for ac_prog in strip do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_AS+:} false; then : +if ${ac_cv_path_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else - case $AS in + case $STRIP in [\\/]* | ?:[\\/]*) - ac_cv_path_AS="$AS" # Let the user override the test with a path. + ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -36011,7 +34661,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -36022,17 +34672,17 @@ IFS=$as_save_IFS ;; esac fi -AS=$ac_cv_path_AS -if test -n "$AS"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 -$as_echo "$AS" >&6; } +STRIP=$ac_cv_path_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$AS" && break + test -n "$STRIP" && break done else @@ -36044,22 +34694,22 @@ done CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" # Check if the provided tool contains a complete path. - tool_specified="$AS" + tool_specified="$STRIP" tool_basename="${tool_specified##*/}" if test "x$tool_basename" = "x$tool_specified"; then # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool AS=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool AS=$tool_basename" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool STRIP=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool STRIP=$tool_basename" >&6;} # Extract the first word of "$tool_basename", so it can be a program name with args. set dummy $tool_basename; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_AS+:} false; then : +if ${ac_cv_path_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else - case $AS in + case $STRIP in [\\/]* | ?:[\\/]*) - ac_cv_path_AS="$AS" # Let the user override the test with a path. + ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -36069,7 +34719,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -36080,29 +34730,29 @@ IFS=$as_save_IFS ;; esac fi -AS=$ac_cv_path_AS -if test -n "$AS"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 -$as_echo "$AS" >&6; } +STRIP=$ac_cv_path_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$AS" = x; then + if test "x$STRIP" = x; then as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 fi else # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool AS=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool AS=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AS" >&5 -$as_echo_n "checking for AS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool STRIP=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool STRIP=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for STRIP" >&5 +$as_echo_n "checking for STRIP... " >&6; } if test ! -x "$tool_specified"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "User supplied tool AS=$tool_specified does not exist or is not executable" "$LINENO" 5 + as_fn_error $? "User supplied tool STRIP=$tool_specified does not exist or is not executable" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 $as_echo "$tool_specified" >&6; } @@ -36116,7 +34766,7 @@ $as_echo "$tool_specified" >&6; } # First separate the path from the arguments. This will split at the first # space. - complete="$AS" + complete="$STRIP" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -36152,14 +34802,14 @@ $as_echo "$tool_specified" >&6; } fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi fi @@ -36179,11 +34829,11 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh elif test -f "${new_path}.cmd"; then input_to_shortpath="${new_path}.cmd" else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of AS, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$new_path\", is invalid." >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi else input_to_shortpath="$new_path" @@ -36230,7 +34880,7 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" # First separate the path from the arguments. This will split at the first # space. - complete="$AS" + complete="$STRIP" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -36275,14 +34925,14 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi fi @@ -36328,7 +34978,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # We're on a posix platform. Hooray! :) # First separate the path from the arguments. This will split at the first # space. - complete="$AS" + complete="$STRIP" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -36347,20 +34997,19 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AS (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving AS (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 $as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi fi @@ -36372,17 +35021,11 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi if test "x$complete" != "x$new_complete"; then - AS="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AS to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting AS to \"$new_complete\"" >&6;} + STRIP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} fi - else - AS="$CC -c" - fi - - - if test "x$OPENJDK_TARGET_OS" = xsolaris; then # Publish this variable in the help. @@ -36805,8 +35448,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving NM (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -37257,8 +35899,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving GNM (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving GNM (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -37289,457 +35930,6 @@ $as_echo "$as_me: Rewriting GNM to \"$new_complete\"" >&6;} - # Publish this variable in the help. - - - if test "x$STRIP" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in strip -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $STRIP in - [\\/]* | ?:[\\/]*) - ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -STRIP=$ac_cv_path_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$STRIP" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !STRIP! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!STRIP!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xSTRIP" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in strip -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $STRIP in - [\\/]* | ?:[\\/]*) - ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -STRIP=$ac_cv_path_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$STRIP" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$STRIP" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool STRIP=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool STRIP=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $STRIP in - [\\/]* | ?:[\\/]*) - ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -STRIP=$ac_cv_path_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$STRIP" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool STRIP=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool STRIP=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for STRIP" >&5 -$as_echo_n "checking for STRIP... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool STRIP=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving STRIP (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - STRIP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} - fi - - # Publish this variable in the help. @@ -38161,8 +36351,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MCS (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving MCS (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -38192,6 +36381,568 @@ $as_echo "$as_me: Rewriting MCS to \"$new_complete\"" >&6;} fi elif test "x$OPENJDK_TARGET_OS" != xwindows; then + # FIXME: we should unify this with the solaris case above. + + + # Publish this variable in the help. + + + if test "x$STRIP" = x; then + # The variable is not set by user, try to locate tool using the code snippet + if test -n "$ac_tool_prefix"; then + for ac_prog in strip + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$STRIP" && break + done +fi +if test -z "$STRIP"; then + ac_ct_STRIP=$STRIP + for ac_prog in strip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_STRIP" && break +done + + if test "x$ac_ct_STRIP" = x; then + STRIP="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +fi + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !STRIP! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!STRIP!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xSTRIP" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + if test -n "$ac_tool_prefix"; then + for ac_prog in strip + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$STRIP" && break + done +fi +if test -z "$STRIP"; then + ac_ct_STRIP=$STRIP + for ac_prog in strip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_STRIP" && break +done + + if test "x$ac_ct_STRIP" = x; then + STRIP="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +fi + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$STRIP" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool STRIP=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool STRIP=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $STRIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +STRIP=$ac_cv_path_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$STRIP" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool STRIP=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool STRIP=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for STRIP" >&5 +$as_echo_n "checking for STRIP... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool STRIP=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$STRIP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$STRIP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$STRIP" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + STRIP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} + fi + # Publish this variable in the help. @@ -38724,8 +37475,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving NM (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -38756,568 +37506,6 @@ $as_echo "$as_me: Rewriting NM to \"$new_complete\"" >&6;} GNM="$NM" - - - # Publish this variable in the help. - - - if test "x$STRIP" = x; then - # The variable is not set by user, try to locate tool using the code snippet - if test -n "$ac_tool_prefix"; then - for ac_prog in strip - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$STRIP" && break - done -fi -if test -z "$STRIP"; then - ac_ct_STRIP=$STRIP - for ac_prog in strip -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_STRIP" && break -done - - if test "x$ac_ct_STRIP" = x; then - STRIP="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -fi - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !STRIP! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!STRIP!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xSTRIP" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of STRIP from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - if test -n "$ac_tool_prefix"; then - for ac_prog in strip - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$STRIP" && break - done -fi -if test -z "$STRIP"; then - ac_ct_STRIP=$STRIP - for ac_prog in strip -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_STRIP" && break -done - - if test "x$ac_ct_STRIP" = x; then - STRIP="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -fi - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$STRIP" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool STRIP=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool STRIP=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $STRIP in - [\\/]* | ?:[\\/]*) - ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -STRIP=$ac_cv_path_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$STRIP" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool STRIP=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool STRIP=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for STRIP" >&5 -$as_echo_n "checking for STRIP... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool STRIP=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin causing which - # to not find them - if test "x$new_path" = x \ - && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ - && test "x`$LS \"$path\" 2>/dev/null`" != x; then - new_path=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file presence. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path="$path" - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $new_path` - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_path - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - fi - - else - # We're on a posix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$STRIP" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving STRIP (as $path) failed, using $path directly." >&6;} - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - STRIP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} - fi - fi # objcopy is used for moving debug symbols to separate files when @@ -39857,8 +38045,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJCOPY (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJCOPY (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -40187,7 +38374,8 @@ $as_echo "$tool_specified" >&6; } if test "x$OBJDUMP" != x; then - # Only used for compare.sh; we can live without it. BASIC_FIXUP_EXECUTABLE bails if argument is missing. + # Only used for compare.sh; we can live without it. BASIC_FIXUP_EXECUTABLE + # bails if argument is missing. if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then @@ -40424,8 +38612,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJDUMP (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJDUMP (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi @@ -40456,26 +38643,48 @@ $as_echo "$as_me: Rewriting OBJDUMP to \"$new_complete\"" >&6;} fi - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + + # Restore old path. + PATH="$OLD_PATH" + + # Restore the flags to the user specified values. + # This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2" + CFLAGS="$ORG_CFLAGS" + CXXFLAGS="$ORG_CXXFLAGS" + OBJCFLAGS="$ORG_OBJCFLAGS" + + +# Finally do some processing after the detection phase + + if test "x$COMPILE_TYPE" = "xcross"; then + # Now we need to find a C/C++ compiler that can build executables for the + # build platform. We can't use the AC_PROG_CC macro, since it can only be + # used once. Also, we need to do this without adding a tools dir to the + # path, otherwise we might pick up cross-compilers which don't use standard + # naming. + + # FIXME: we should list the discovered compilers as an exclude pattern! + # If we do that, we can do this detection before POST_DETECTION, and still + # find the build compilers in the tools dir, if needed. # Publish this variable in the help. - if test "x$LIPO" = x; then + if test "x$BUILD_CC" = x; then # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in lipo + for ac_prog in cl cc gcc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIPO+:} false; then : +if ${ac_cv_path_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else - case $LIPO in + case $BUILD_CC in [\\/]* | ?:[\\/]*) - ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. + ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -40485,7 +38694,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -40496,44 +38705,44 @@ IFS=$as_save_IFS ;; esac fi -LIPO=$ac_cv_path_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } +BUILD_CC=$ac_cv_path_BUILD_CC +if test -n "$BUILD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 +$as_echo "$BUILD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$LIPO" && break + test -n "$BUILD_CC" && break done else # The variable is set, but is it from the command line or the environment? - # Try to remove the string !LIPO! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!LIPO!/} + # Try to remove the string !BUILD_CC! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_CC!/} if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then # If it failed, the variable was not from the command line. Ignore it, # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xLIPO" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of LIPO from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of LIPO from the environment. Use command line variables instead." >&2;} + if test "xBUILD_CC" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_CC from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of BUILD_CC from the environment. Use command line variables instead." >&2;} fi # Try to locate tool using the code snippet - for ac_prog in lipo + for ac_prog in cl cc gcc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIPO+:} false; then : +if ${ac_cv_path_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else - case $LIPO in + case $BUILD_CC in [\\/]* | ?:[\\/]*) - ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. + ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -40543,7 +38752,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -40554,17 +38763,17 @@ IFS=$as_save_IFS ;; esac fi -LIPO=$ac_cv_path_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } +BUILD_CC=$ac_cv_path_BUILD_CC +if test -n "$BUILD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 +$as_echo "$BUILD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$LIPO" && break + test -n "$BUILD_CC" && break done else @@ -40576,22 +38785,22 @@ done CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" # Check if the provided tool contains a complete path. - tool_specified="$LIPO" + tool_specified="$BUILD_CC" tool_basename="${tool_specified##*/}" if test "x$tool_basename" = "x$tool_specified"; then # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool LIPO=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool LIPO=$tool_basename" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_CC=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool BUILD_CC=$tool_basename" >&6;} # Extract the first word of "$tool_basename", so it can be a program name with args. set dummy $tool_basename; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIPO+:} false; then : +if ${ac_cv_path_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else - case $LIPO in + case $BUILD_CC in [\\/]* | ?:[\\/]*) - ac_cv_path_LIPO="$LIPO" # Let the user override the test with a path. + ac_cv_path_BUILD_CC="$BUILD_CC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -40601,7 +38810,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIPO="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_BUILD_CC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -40612,29 +38821,29 @@ IFS=$as_save_IFS ;; esac fi -LIPO=$ac_cv_path_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } +BUILD_CC=$ac_cv_path_BUILD_CC +if test -n "$BUILD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 +$as_echo "$BUILD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$LIPO" = x; then + if test "x$BUILD_CC" = x; then as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 fi else # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool LIPO=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool LIPO=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIPO" >&5 -$as_echo_n "checking for LIPO... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_CC=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool BUILD_CC=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_CC" >&5 +$as_echo_n "checking for BUILD_CC... " >&6; } if test ! -x "$tool_specified"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "User supplied tool LIPO=$tool_specified does not exist or is not executable" "$LINENO" 5 + as_fn_error $? "User supplied tool BUILD_CC=$tool_specified does not exist or is not executable" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 $as_echo "$tool_specified" >&6; } @@ -40648,7 +38857,7 @@ $as_echo "$tool_specified" >&6; } # First separate the path from the arguments. This will split at the first # space. - complete="$LIPO" + complete="$BUILD_CC" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -40684,14 +38893,14 @@ $as_echo "$tool_specified" >&6; } fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 fi fi @@ -40711,11 +38920,11 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh elif test -f "${new_path}.cmd"; then input_to_shortpath="${new_path}.cmd" else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of LIPO, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$new_path\", is invalid." >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 fi else input_to_shortpath="$new_path" @@ -40762,7 +38971,7 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" # First separate the path from the arguments. This will split at the first # space. - complete="$LIPO" + complete="$BUILD_CC" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -40807,14 +39016,14 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 fi fi @@ -40860,7 +39069,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # We're on a posix platform. Hooray! :) # First separate the path from the arguments. This will split at the first # space. - complete="$LIPO" + complete="$BUILD_CC" path="${complete%% *}" tmp="$complete EOL" arguments="${tmp#* }" @@ -40879,20 +39088,19 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh done IFS="$IFS_save" else - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving LIPO (as $path) failed, using $path directly." >&5 -$as_echo "$as_me: Resolving LIPO (as $path) failed, using $path directly." >&6;} + # This is an absolute path, we can use it without further modifications. new_path="$path" fi if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 $as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} fi - as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 + as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 fi fi @@ -40904,22 +39112,1507 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi if test "x$complete" != "x$new_complete"; then - LIPO="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting LIPO to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting LIPO to \"$new_complete\"" >&6;} - fi - + BUILD_CC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CC to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting BUILD_CC to \"$new_complete\"" >&6;} fi - # Restore old path without tools dir - PATH="$OLD_PATH" + # Publish this variable in the help. -# FIXME: Currently we must test this after paths but before flags. Fix! + if test "x$BUILD_CXX" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in cl CC g++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS -# And we can test some aspects on the target using configure macros. + ;; +esac +fi +BUILD_CXX=$ac_cv_path_BUILD_CXX +if test -n "$BUILD_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 +$as_echo "$BUILD_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$BUILD_CXX" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !BUILD_CXX! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_CXX!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xBUILD_CXX" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_CXX from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of BUILD_CXX from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in cl CC g++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +BUILD_CXX=$ac_cv_path_BUILD_CXX +if test -n "$BUILD_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 +$as_echo "$BUILD_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$BUILD_CXX" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$BUILD_CXX" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_CXX=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool BUILD_CXX=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_CXX="$BUILD_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +BUILD_CXX=$ac_cv_path_BUILD_CXX +if test -n "$BUILD_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CXX" >&5 +$as_echo "$BUILD_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$BUILD_CXX" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_CXX=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool BUILD_CXX=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_CXX" >&5 +$as_echo_n "checking for BUILD_CXX... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool BUILD_CXX=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_CXX" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_CXX" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_CXX" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + BUILD_CXX="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CXX to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting BUILD_CXX to \"$new_complete\"" >&6;} + fi + + + + # Publish this variable in the help. + + + if test "x$BUILD_LD" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in ld +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_LD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +BUILD_LD=$ac_cv_path_BUILD_LD +if test -n "$BUILD_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 +$as_echo "$BUILD_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$BUILD_LD" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !BUILD_LD! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_LD!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xBUILD_LD" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_LD from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of BUILD_LD from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in ld +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_LD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +BUILD_LD=$ac_cv_path_BUILD_LD +if test -n "$BUILD_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 +$as_echo "$BUILD_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$BUILD_LD" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$BUILD_LD" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_LD=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool BUILD_LD=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BUILD_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BUILD_LD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BUILD_LD="$BUILD_LD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BUILD_LD="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +BUILD_LD=$ac_cv_path_BUILD_LD +if test -n "$BUILD_LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LD" >&5 +$as_echo "$BUILD_LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$BUILD_LD" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_LD=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool BUILD_LD=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_LD" >&5 +$as_echo_n "checking for BUILD_LD... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool BUILD_LD=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path=`$CYGPATH -u "$path"` + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path=`$CYGPATH -u "$path"` + new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in cygwin causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path=`$CYGPATH -u "$path"` + fi + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 + fi + fi + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file presence. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + # Short path failed, file does not exist as specified. + # Try adding .exe or .cmd + if test -f "${new_path}.exe"; then + input_to_shortpath="${new_path}.exe" + elif test -f "${new_path}.cmd"; then + input_to_shortpath="${new_path}.cmd" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$new_path\", is invalid." >&5 +$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$new_path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 +$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} + as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 + fi + else + input_to_shortpath="$new_path" + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + new_path="$input_to_shortpath" + + input_path="$input_to_shortpath" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Input might be given as Windows format, start by converting to + # unix format. + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + # Now try to locate executable using which + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # Oops. Which didn't find the executable. + # The splitting of arguments from the executable at a space might have been incorrect, + # since paths with space are more likely in Windows. Give it another try with the whole + # argument. + path="$complete" + arguments="EOL" + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + + new_path=`$WHICH "$new_path" 2> /dev/null` + + if test "x$new_path" = x; then + # It's still not found. Now this is an unrecoverable error. + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 +$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 + fi + fi + + # Now new_path has a complete unix path to the binary + if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then + # Keep paths in /bin as-is, but remove trailing .exe if any + new_path="${new_path/%.exe/}" + # Do not save /bin paths to all_fixpath_prefixes! + else + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $new_path` + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + # Output is in $new_path + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + # remove trailing .exe if any + new_path="${new_path/%.exe/}" + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + fi + + else + # We're on a posix platform. Hooray! :) + # First separate the path from the arguments. This will split at the first + # space. + complete="$BUILD_LD" + path="${complete%% *}" + tmp="$complete EOL" + arguments="${tmp#* }" + + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + # This is an absolute path, we can use it without further modifications. + new_path="$path" + fi + + if test "x$new_path" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 +$as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} + has_space=`$ECHO "$complete" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 +$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} + fi + as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 + fi + fi + + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi + + if test "x$complete" != "x$new_complete"; then + BUILD_LD="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_LD to \"$new_complete\"" >&5 +$as_echo "$as_me: Rewriting BUILD_LD to \"$new_complete\"" >&6;} + fi + + else + # If we are not cross compiling, use the normal target compilers for + # building the build platform executables. + BUILD_CC="$CC" + BUILD_CXX="$CXX" + BUILD_LD="$LD" + fi + + + + + + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # For hotspot, we need these in Windows mixed path, + # so rewrite them all. Need added .exe suffix. + HOTSPOT_CXX="$CXX.exe" + HOTSPOT_LD="$LD.exe" + HOTSPOT_MT="$MT.exe" + HOTSPOT_RC="$RC.exe" + + unix_path="$HOTSPOT_CXX" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + HOTSPOT_CXX="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + HOTSPOT_CXX="$windows_path" + fi + + + unix_path="$HOTSPOT_LD" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + HOTSPOT_LD="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + HOTSPOT_LD="$windows_path" + fi + + + unix_path="$HOTSPOT_MT" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + HOTSPOT_MT="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + HOTSPOT_MT="$windows_path" + fi + + + unix_path="$HOTSPOT_RC" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + HOTSPOT_RC="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + HOTSPOT_RC="$windows_path" + fi + + + + else + HOTSPOT_CXX="$CXX" + HOTSPOT_LD="$LD" + fi + + + + if test "x$TOOLCHAIN_TYPE" = xclang; then + USE_CLANG=true + fi + + + # LDEXE is the linker to use, when creating executables. Not really used. + # FIXME: These should just be removed! + LDEXE="$LD" + LDEXECXX="$LDCXX" + + + + + # The package path is used only on macosx? + # FIXME: clean this up, and/or move it elsewhere. + PACKAGE_PATH=/opt/local + + + # Check for extra potential brokenness. + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # On Windows, double-check that we got the right compiler. + CC_VERSION_OUTPUT=`$CC 2>&1 | $HEAD -n 1 | $TR -d '\r'` + COMPILER_CPU_TEST=`$ECHO $CC_VERSION_OUTPUT | $SED -n "s/^.* \(.*\)$/\1/p"` + if test "x$OPENJDK_TARGET_CPU" = "xx86"; then + if test "x$COMPILER_CPU_TEST" != "x80x86"; then + as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"80x86\"." "$LINENO" 5 + fi + elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + if test "x$COMPILER_CPU_TEST" != "xx64"; then + as_fn_error $? "Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for \"$COMPILER_CPU_TEST\"; expected \"x64\"." "$LINENO" 5 + fi + fi + fi + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + # If this is a --hash-style=gnu system, use --hash-style=both, why? + HAS_GNU_HASH=`$CC -dumpspecs 2>/dev/null | $GREP 'hash-style=gnu'` + # This is later checked when setting flags. + fi + + # Check for broken SuSE 'ld' for which 'Only anonymous version tag is allowed + # in executable.' + USING_BROKEN_SUSE_LD=no + if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$TOOLCHAIN_TYPE" = xgcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken SuSE 'ld' which only understands anonymous version tags in executables" >&5 +$as_echo_n "checking for broken SuSE 'ld' which only understands anonymous version tags in executables... " >&6; } + echo "SUNWprivate_1.1 { local: *; };" > version-script.map + echo "int main() { }" > main.c + if $CXX -Xlinker -version-script=version-script.map main.c 2>&5 >&5; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + USING_BROKEN_SUSE_LD=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + USING_BROKEN_SUSE_LD=yes + fi + rm -rf version-script.map main.c a.out + fi + + + +# Setup the JTReg Regression Test Harness. + + +# Check whether --with-jtreg was given. +if test "${with_jtreg+set}" = set; then : + withval=$with_jtreg; +else + with_jtreg=no +fi + + + if test "x$with_jtreg" = xno; then + # jtreg disabled + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5 +$as_echo_n "checking for jtreg... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + if test "x$with_jtreg" != xyes; then + # with path specified. + JT_HOME="$with_jtreg" + fi + + if test "x$JT_HOME" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jtreg" >&5 +$as_echo_n "checking for jtreg... " >&6; } + + # use JT_HOME enviroment var. + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$JT_HOME" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of JT_HOME" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + JT_HOME="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$JT_HOME" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + JT_HOME="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$JT_HOME" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of JT_HOME, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + JT_HOME="`cd "$path"; $THEPWDCMD -L`" + fi + + + # jtreg win32 script works for everybody + JTREGEXE="$JT_HOME/win32/bin/jtreg" + + if test ! -f "$JTREGEXE"; then + as_fn_error $? "JTReg executable does not exist: $JTREGEXE" "$LINENO" 5 + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 +$as_echo "$JTREGEXE" >&6; } + else + # try to find jtreg on path + + + + # Publish this variable in the help. + + + if test "x$JTREGEXE" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in jtreg +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_JTREGEXE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $JTREGEXE in + [\\/]* | ?:[\\/]*) + ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +JTREGEXE=$ac_cv_path_JTREGEXE +if test -n "$JTREGEXE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 +$as_echo "$JTREGEXE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JTREGEXE" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !JTREGEXE! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!JTREGEXE!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xJTREGEXE" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of JTREGEXE from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of JTREGEXE from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in jtreg +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_JTREGEXE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $JTREGEXE in + [\\/]* | ?:[\\/]*) + ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +JTREGEXE=$ac_cv_path_JTREGEXE +if test -n "$JTREGEXE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 +$as_echo "$JTREGEXE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JTREGEXE" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$JTREGEXE" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool JTREGEXE=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool JTREGEXE=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_JTREGEXE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $JTREGEXE in + [\\/]* | ?:[\\/]*) + ac_cv_path_JTREGEXE="$JTREGEXE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_JTREGEXE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +JTREGEXE=$ac_cv_path_JTREGEXE +if test -n "$JTREGEXE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JTREGEXE" >&5 +$as_echo "$JTREGEXE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$JTREGEXE" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool JTREGEXE=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool JTREGEXE=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JTREGEXE" >&5 +$as_echo_n "checking for JTREGEXE... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool JTREGEXE=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$JTREGEXE" = x; then + as_fn_error $? "Could not find required tool for JTREGEXE" "$LINENO" 5 + fi + + + JT_HOME="`$DIRNAME $JTREGEXE`" + fi + fi + + + + + + + # Option used to tell the compiler whether to create 32- or 64-bit executables + if test "x$TOOLCHAIN_TYPE" = xxlc; then + COMPILER_TARGET_BITS_FLAG="-q" + else + COMPILER_TARGET_BITS_FLAG="-m" + fi + + + # FIXME: figure out if we should select AR flags depending on OS or toolchain. + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + ARFLAGS="-r" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + ARFLAGS="-X64" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + # lib.exe is used as AR to create static libraries. + ARFLAGS="-nologo -NODEFAULTLIB:MSVCRT" + else + ARFLAGS="" + fi + + + ## Setup strip. + # FIXME: should this really be per platform, or should it be per toolchain type? + # strip is not provided by clang or solstudio; so guessing platform makes most sense. + # FIXME: we should really only export STRIPFLAGS from here, not POST_STRIP_CMD. + if test "x$OPENJDK_TARGET_OS" = xlinux; then + STRIPFLAGS="-g" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + STRIPFLAGS="-x" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + STRIPFLAGS="-S" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + STRIPFLAGS="-X32_64" + fi + + if test "x$OPENJDK_TARGET_OS" != xwindows; then + POST_STRIP_CMD="$STRIP $STRIPFLAGS" + fi + + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: break out into MCSFLAGS + POST_MCS_CMD="$MCS -d -a \"JDK $FULL_VERSION\"" + fi + + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + CC_OUT_OPTION=-Fo + EXE_OUT_OPTION=-out: + LD_OUT_OPTION=-out: + AR_OUT_OPTION=-out: + else + # The option used to specify the target .o,.a or .so file. + # When compiling, how to specify the to be created object file. + CC_OUT_OPTION='-o$(SPACE)' + # When linking, how to specify the to be created executable. + EXE_OUT_OPTION='-o$(SPACE)' + # When linking, how to specify the to be created dynamically linkable library. + LD_OUT_OPTION='-o$(SPACE)' + # When archiving, how to specify the to be create static archive for object files. + AR_OUT_OPTION='rcs$(SPACE)' + fi + + + + + + # On Windows, we need to set RC flags. + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + RC_FLAGS="-nologo -l 0x409 -r" + if test "x$VARIANT" = xOPT; then + RC_FLAGS="$RC_FLAGS -d NDEBUG" + fi + + # The version variables used to create RC_FLAGS may be overridden + # in a custom configure script, or possibly the command line. + # Let those variables be expanded at make time in spec.gmk. + # The \$ are escaped to the shell, and the $(...) variables + # are evaluated by make. + RC_FLAGS="$RC_FLAGS \ + -d \"JDK_BUILD_ID=\$(FULL_VERSION)\" \ + -d \"JDK_COMPANY=\$(COMPANY_NAME)\" \ + -d \"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \ + -d \"JDK_VER=\$(JDK_MINOR_VERSION).\$(JDK_MICRO_VERSION).\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0).\$(COOKED_BUILD_NUMBER)\" \ + -d \"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ + -d \"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(JDK_MINOR_VERSION) \$(JDK_UPDATE_META_TAG)\" \ + -d \"JDK_FVER=\$(JDK_MINOR_VERSION),\$(JDK_MICRO_VERSION),\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0),\$(COOKED_BUILD_NUMBER)\"" + fi + + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # FIXME: likely bug, should be CCXXFLAGS_JDK? or one for C or CXX. + CCXXFLAGS="$CCXXFLAGS -nologo" + fi + + +# FIXME: Currently we must test this after toolchain but before flags. Fix! + +# Now we can test some aspects on the target using configure macros. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 @@ -41486,114 +41179,58 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # Configure flags for the tools - ############################################################################### # # How to compile shared libraries. # - if test "x$GCC" = xyes; then - COMPILER_NAME=gcc + if test "x$TOOLCHAIN_TYPE" = xgcc; then PICFLAG="-fPIC" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib$1.so' - STATIC_LIBRARY='lib$1.a' - SHARED_LIBRARY_FLAGS="-shared" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='-Xlinker -soname=$1' - SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=$1' C_FLAG_REORDER='' CXX_FLAG_REORDER='' - SET_SHARED_LIBRARY_ORIGIN='-Xlinker -z -Xlinker origin -Xlinker -rpath -Xlinker \$$$$ORIGIN$1' - SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN$1' - LD="$CC" - LDEXE="$CC" - LDCXX="$CXX" - LDEXECXX="$CXX" - POST_STRIP_CMD="$STRIP -g" - # Linking is different on MacOSX if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # Might change in the future to clang. - COMPILER_NAME=gcc - SHARED_LIBRARY='lib$1.dylib' + # Linking is different on MacOSX SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" - SHARED_LIBRARY_SUFFIX='.dylib' - EXE_SUFFIX='' + SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.' + SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/$1' SET_SHARED_LIBRARY_MAPFILE='' - SET_SHARED_LIBRARY_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.' - SET_EXECUTABLE_ORIGIN="$SET_SHARED_LIBRARY_ORIGIN" - POST_STRIP_CMD="$STRIP -S" - fi - else - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - # If it is not gcc, then assume it is the Oracle Solaris Studio Compiler - COMPILER_NAME=ossc - PICFLAG="-KPIC" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib$1.so' - STATIC_LIBRARY='lib$1.a' - SHARED_LIBRARY_FLAGS="-G" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='-M$1' - C_FLAG_REORDER='-xF' - CXX_FLAG_REORDER='-xF' - SET_SHARED_LIBRARY_ORIGIN='-R\$$$$ORIGIN$1' - SET_EXECUTABLE_ORIGIN="$SET_SHARED_LIBRARY_ORIGIN" - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - POST_STRIP_CMD="$STRIP -x" - POST_MCS_CMD="$MCS -d -a \"JDK $FULL_VERSION\"" - fi - if test "x$OPENJDK_TARGET_OS" = xaix; then - COMPILER_NAME=xlc - PICFLAG="-qpic=large" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib$1.so' - STATIC_LIBRARY='lib$1.a' - SHARED_LIBRARY_FLAGS="-qmkshrobj" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='' - C_FLAG_REORDER='' - CXX_FLAG_REORDER='' - SET_SHARED_LIBRARY_ORIGIN='' - SET_EXECUTABLE_ORIGIN="" - CFLAGS_JDK="" - CXXFLAGS_JDK="" - CFLAGS_JDKLIB_EXTRA='' - POST_STRIP_CMD="$STRIP -X32_64" - POST_MCS_CMD="" - fi - if test "x$OPENJDK_TARGET_OS" = xwindows; then - # If it is not gcc, then assume it is the MS Visual Studio compiler - COMPILER_NAME=cl - PICFLAG="" - LIBRARY_PREFIX= - SHARED_LIBRARY='$1.dll' - STATIC_LIBRARY='$1.lib' - SHARED_LIBRARY_FLAGS="-LD" - SHARED_LIBRARY_SUFFIX='.dll' - STATIC_LIBRARY_SUFFIX='.lib' - OBJ_SUFFIX='.obj' - EXE_SUFFIX='.exe' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='' - SET_SHARED_LIBRARY_ORIGIN='' - SET_EXECUTABLE_ORIGIN='' + else + # Default works for linux, might work on other platforms as well. + SHARED_LIBRARY_FLAGS='-shared' + SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN$1' + SET_SHARED_LIBRARY_ORIGIN="-Xlinker -z -Xlinker origin $SET_EXECUTABLE_ORIGIN" + SET_SHARED_LIBRARY_NAME='-Xlinker -soname=$1' + SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=$1' fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + PICFLAG="-KPIC" + C_FLAG_REORDER='-xF' + CXX_FLAG_REORDER='-xF' + SHARED_LIBRARY_FLAGS="-G" + SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN$1' + SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" + SET_SHARED_LIBRARY_NAME='' + SET_SHARED_LIBRARY_MAPFILE='-M$1' + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + PICFLAG="-qpic=large" + C_FLAG_REORDER='' + CXX_FLAG_REORDER='' + SHARED_LIBRARY_FLAGS="-qmkshrobj" + SET_EXECUTABLE_ORIGIN="" + SET_SHARED_LIBRARY_ORIGIN='' + SET_SHARED_LIBRARY_NAME='' + SET_SHARED_LIBRARY_MAPFILE='' + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + PICFLAG="" + C_FLAG_REORDER='' + CXX_FLAG_REORDER='' + SHARED_LIBRARY_FLAGS="-LD" + SET_EXECUTABLE_ORIGIN='' + SET_SHARED_LIBRARY_ORIGIN='' + SET_SHARED_LIBRARY_NAME='' + SET_SHARED_LIBRARY_MAPFILE='' fi @@ -41604,16 +41241,11 @@ $as_echo "$ac_cv_c_bigendian" >&6; } - - - - - - - - - - + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. @@ -41625,181 +41257,102 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # and different operating systems. # - # - # NOTE: check for -mstackrealign needs to be below potential addition of -m32 - # - if test "x$OPENJDK_TARGET_CPU_BITS" = x32 && test "x$OPENJDK_TARGET_OS" = xmacosx; then - # On 32-bit MacOSX the OS requires C-entry points to be 16 byte aligned. - # While waiting for a better solution, the current workaround is to use -mstackrealign. - CFLAGS="$CFLAGS -mstackrealign" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 32-bit compiler supports -mstackrealign" >&5 -$as_echo_n "checking if 32-bit compiler supports -mstackrealign... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int main() { return 0; } -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : + # FIXME: this was indirectly the old default, but just inherited. + # if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # C_FLAG_DEPS="-MMD -MF" + # fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - as_fn_error $? "The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path." "$LINENO" 5 + # Generate make dependency files + if test "x$TOOLCHAIN_TYPE" = xgcc; then + C_FLAG_DEPS="-MMD -MF" + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + C_FLAG_DEPS="-xMMD -xMF" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_FLAG_DEPS="-qmakedep=gcc -MF" + fi + CXX_FLAG_DEPS="$C_FLAG_DEPS" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext + + # Debug symbols + if test "x$TOOLCHAIN_TYPE" = xgcc; then + if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then + CFLAGS_DEBUG_SYMBOLS="-g1" + CXXFLAGS_DEBUG_SYMBOLS="-g1" + else + CFLAGS_DEBUG_SYMBOLS="-g" + CXXFLAGS_DEBUG_SYMBOLS="-g" + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + CFLAGS_DEBUG_SYMBOLS="-g -xs" + CXXFLAGS_DEBUG_SYMBOLS="-g0 -xs" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + CFLAGS_DEBUG_SYMBOLS="-g" + CXXFLAGS_DEBUG_SYMBOLS="-g" fi - C_FLAG_DEPS="-MMD -MF" - CXX_FLAG_DEPS="-MMD -MF" - case $COMPILER_TYPE in - CC ) - case $COMPILER_NAME in - gcc ) - case $OPENJDK_TARGET_OS in - macosx ) - # On MacOSX we optimize for size, something - # we should do for all platforms? - C_O_FLAG_HI="-Os" - C_O_FLAG_NORM="-Os" - C_O_FLAG_NONE="" - ;; - *) - C_O_FLAG_HI="-O3" - C_O_FLAG_NORM="-O2" - C_O_FLAG_NONE="-O0" - ;; - esac - CXX_O_FLAG_HI="$C_O_FLAG_HI" - CXX_O_FLAG_NORM="$C_O_FLAG_NORM" - CXX_O_FLAG_NONE="$C_O_FLAG_NONE" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then - CFLAGS_DEBUG_SYMBOLS="-g1" - CXXFLAGS_DEBUG_SYMBOLS="-g1" - fi - ;; - ossc ) - # - # Forte has different names for this with their C++ compiler... - # - C_FLAG_DEPS="-xMMD -xMF" - CXX_FLAG_DEPS="-xMMD -xMF" - # Extra options used with HIGHEST - # - # WARNING: Use of OPTIMIZATION_LEVEL=HIGHEST in your Makefile needs to be - # done with care, there are some assumptions below that need to - # be understood about the use of pointers, and IEEE behavior. - # - # Use non-standard floating point mode (not IEEE 754) - CC_HIGHEST="$CC_HIGHEST -fns" - # Do some simplification of floating point arithmetic (not IEEE 754) - CC_HIGHEST="$CC_HIGHEST -fsimple" - # Use single precision floating point with 'float' - CC_HIGHEST="$CC_HIGHEST -fsingle" - # Assume memory references via basic pointer types do not alias - # (Source with excessing pointer casting and data access with mixed - # pointer types are not recommended) - CC_HIGHEST="$CC_HIGHEST -xalias_level=basic" - # Use intrinsic or inline versions for math/std functions - # (If you expect perfect errno behavior, do not use this) - CC_HIGHEST="$CC_HIGHEST -xbuiltin=%all" - # Loop data dependency optimizations (need -xO3 or higher) - CC_HIGHEST="$CC_HIGHEST -xdepend" - # Pointer parameters to functions do not overlap - # (Similar to -xalias_level=basic usage, but less obvious sometimes. - # If you pass in multiple pointers to the same data, do not use this) - CC_HIGHEST="$CC_HIGHEST -xrestrict" - # Inline some library routines - # (If you expect perfect errno behavior, do not use this) - CC_HIGHEST="$CC_HIGHEST -xlibmil" - # Use optimized math routines - # (If you expect perfect errno behavior, do not use this) - # Can cause undefined external on Solaris 8 X86 on __sincos, removing for now - #CC_HIGHEST="$CC_HIGHEST -xlibmopt" + # Optimization levels + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xalias_level=basic -xbuiltin=%all -xdepend -xrestrict -xlibmil" - if test "x$OPENJDK_TARGET_CPU" = xsparc; then - CFLAGS_JDK="${CFLAGS_JDK} -xmemalign=4s" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -xmemalign=4s" - fi - - case $OPENJDK_TARGET_CPU_ARCH in - x86) - C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xregs=no%frameptr" - C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" - C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" - C_O_FLAG_NONE="-xregs=no%frameptr" - CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" - CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" - CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" - CXX_O_FLAG_NONE="-xregs=no%frameptr" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" - CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" - fi - ;; - sparc) - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" - C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" - C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" - C_O_FLAG_NONE="" - CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" - CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" - CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" - CXX_O_FLAG_NONE="" - ;; - esac - - CFLAGS_DEBUG_SYMBOLS="-g -xs" - CXXFLAGS_DEBUG_SYMBOLS="-g0 -xs" - ;; - xlc ) - C_FLAG_DEPS="-qmakedep=gcc -MF" - CXX_FLAG_DEPS="-qmakedep=gcc -MF" - C_O_FLAG_HIGHEST="-O3" - C_O_FLAG_HI="-O3 -qstrict" - C_O_FLAG_NORM="-O2" - C_O_FLAG_NONE="" - CXX_O_FLAG_HIGHEST="-O3" - CXX_O_FLAG_HI="-O3 -qstrict" - CXX_O_FLAG_NORM="-O2" - CXX_O_FLAG_NONE="" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - ;; - esac - ;; - CL ) + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then + # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xregs=no%frameptr" + C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" + C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" + C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" + CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" + CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" + CXX_O_FLAG_NONE="-xregs=no%frameptr" + if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then + C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" + CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" + fi + elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" + C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" + C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" + C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" + CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" + CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" + CXX_O_FLAG_NONE="" + fi + else + # The remaining toolchains share opt flags between CC and CXX; + # setup for C and duplicate afterwards. + if test "x$TOOLCHAIN_TYPE" = xgcc; then + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + # On MacOSX we optimize for size, something + # we should do for all platforms? + C_O_FLAG_HIGHEST="-Os" + C_O_FLAG_HI="-Os" + C_O_FLAG_NORM="-Os" + C_O_FLAG_NONE="" + else + C_O_FLAG_HIGHEST="-O3" + C_O_FLAG_HI="-O3" + C_O_FLAG_NORM="-O2" + C_O_FLAG_NONE="-O0" + fi + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST="-O3" + C_O_FLAG_HI="-O3 -qstrict" + C_O_FLAG_NORM="-O2" + C_O_FLAG_NONE="" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_NONE="-Od" - CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" - CXX_O_FLAG_HI="$C_O_FLAG_HI" - CXX_O_FLAG_NORM="$C_O_FLAG_NORM" - CXX_O_FLAG_NONE="$C_O_FLAG_NONE" - ;; - esac - - if test -z "$C_O_FLAG_HIGHEST"; then - C_O_FLAG_HIGHEST="$C_O_FLAG_HI" - fi - - if test -z "$CXX_O_FLAG_HIGHEST"; then - CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HI" + fi + CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" + CXX_O_FLAG_HI="$C_O_FLAG_HI" + CXX_O_FLAG_NORM="$C_O_FLAG_NORM" + CXX_O_FLAG_NONE="$C_O_FLAG_NONE" fi @@ -41812,8 +41365,17 @@ rm -f core conftest.err conftest.$ac_objext \ - - + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" + fi if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring CFLAGS($CFLAGS) found in environment. Use --with-extra-cflags" >&5 @@ -41869,63 +41431,49 @@ fi # Now setup the CFLAGS and LDFLAGS for the JDK build. # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. # - case $COMPILER_NAME in - gcc ) - # these options are used for both C and C++ compiles - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe \ - -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - arm ) - # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - ppc ) - # on ppc we don't prevent gcc to omit frame pointer nor strict-aliasing - ;; - * ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - ;; - ossc ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" - case $OPENJDK_TARGET_CPU_ARCH in - x86 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" - CFLAGS_JDK="$CFLAGS_JDK -erroff=E_BAD_PRAGMA_PACK_VALUE" - ;; - esac - CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" - CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + # Setup compiler/platform specific flags to CFLAGS_JDK, + # CXXFLAGS_JDK and CCXXFLAGS_JDK (common to C and CXX?) + if test "x$TOOLCHAIN_TYPE" = xgcc; then + # these options are used for both C and C++ compiles + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_TARGET_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer nor strict-aliasing + ;; + * ) + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer" + CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" + CFLAGS_JDK="$CFLAGS_JDK -erroff=E_BAD_PRAGMA_PACK_VALUE" + fi - LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" - ;; - xlc ) - CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - - LDFLAGS_JDK="$LDFLAGS_JDK" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK" - ;; - cl ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Zi -MD -Zc:wchar_t- -W3 -wd4800 \ - -D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB -DWIN32_LEAN_AND_MEAN \ - -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ - -DWIN32 -DIAL" - case $OPENJDK_TARGET_CPU in - x86 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_X86_ -Dx86" - ;; - x86_64 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_AMD64_ -Damd64" - ;; - esac - ;; - esac + CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Zi -MD -Zc:wchar_t- -W3 -wd4800 \ + -D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -DWIN32 -DIAL" + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + fi ############################################################################### @@ -41951,12 +41499,13 @@ fi ;; esac + # Setup LP64 CCXXFLAGS_JDK="$CCXXFLAGS_JDK $ADD_LP64" - # The package path is used only on macosx? - PACKAGE_PATH=/opt/local - + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + # Setup endianness if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN @@ -41971,47 +41520,60 @@ fi else CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN" fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DLINUX" - fi - if test "x$OPENJDK_TARGET_OS" = xwindows; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DWINDOWS" - fi - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DSOLARIS" - fi - if test "x$OPENJDK_TARGET_OS" = xaix; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DAIX -DPPC64" - fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMACOSX -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" - # Setting these parameters makes it an error to link to macosx APIs that are - # newer than the given OS version and makes the linked binaries compatible even - # if built on a newer version of the OS. - # The expected format is X.Y.Z - MACOSX_VERSION_MIN=10.7.0 - # The macro takes the version with no dots, ex: 1070 - # Let the flags variables get resolved in make for easier override on make - # command line. - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - fi - if test "x$OPENJDK_TARGET_OS" = xbsd; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DBSD -D_ALLBSD_SOURCE" - fi + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_TARGET_OS_UPPERCASE=`$ECHO $OPENJDK_TARGET_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" + + # Setup target CPU + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" + + # Setup debug/release defines if test "x$DEBUG_LEVEL" = xrelease; then CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DNDEBUG" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DTRIMMED" - fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DTRIMMED" + fi else CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DDEBUG" fi - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" + # Setup release name CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DRELEASE='\"\$(RELEASE)\"'" + + # Set some additional per-OS defines. + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + # FIXME: PPC64 should not be here. + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DPPC64" + elif test "x$OPENJDK_TARGET_OS" = xbsd; then + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + fi + + # Additional macosx handling + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + if test "x$TOOLCHAIN_TYPE" = xgcc; then + # FIXME: This needs to be exported in spec.gmk due to closed legacy code. + # FIXME: clean this up, and/or move it elsewhere. + + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + fi + + # Setup some hard coded includes CCXXFLAGS_JDK="$CCXXFLAGS_JDK \ -I${JDK_OUTPUTDIR}/include \ -I${JDK_OUTPUTDIR}/include/$OPENJDK_TARGET_OS \ @@ -42028,6 +41590,13 @@ fi CFLAGS_JDKEXE="$CCXXFLAGS_JDK $CFLAGS_JDK" CXXFLAGS_JDKEXE="$CCXXFLAGS_JDK $CXXFLAGS_JDK" + + + + + + # Setup LDFLAGS et al. + # # Now this is odd. The JDK native libraries have to link against libjvm.so # On 32-bit machines there is normally two distinct libjvm.so:s, client and server. # Which should we link to? Are we lucky enough that the binary api to the libjvm.so library @@ -42036,9 +41605,9 @@ fi # libraries will link to whatever is in memory. Yuck. # # Thus we offer the compiler to find libjvm.so first in server then in client. It works. Ugh. - if test "x$COMPILER_NAME" = xcl; then + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_JDK="$LDFLAGS_JDK -nologo -opt:ref -incremental:no" - if test "x$OPENJDK_TARGET_CPU" = xx86; then + if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then LDFLAGS_JDK="$LDFLAGS_JDK -safeseh" fi # TODO: make -debug optional "--disable-full-debug-symbols" @@ -42052,9 +41621,9 @@ fi fi LDFLAGS_JDKEXE="${LDFLAGS_JDK} /STACK:$LDFLAGS_STACK_SIZE" else - if test "x$COMPILER_NAME" = xgcc; then + if test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? - HAS_GNU_HASH=`$CC -dumpspecs 2>/dev/null | $GREP 'hash-style=gnu'` + # We have previously set HAS_GNU_HASH if this is the case if test -n "$HAS_GNU_HASH"; then LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker --hash-style=both " fi @@ -42069,6 +41638,12 @@ fi fi fi fi + + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" + LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" + fi + LDFLAGS_JDKLIB="${LDFLAGS_JDK} $SHARED_LIBRARY_FLAGS \ -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}" @@ -42087,7 +41662,7 @@ fi fi LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm" - if test "x$COMPILER_NAME" = xossc; then + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc" fi @@ -42104,13 +41679,6 @@ fi - - - - - - - # Some Zero and Shark settings. # ZERO_ARCHFLAG tells the compiler which mode to build for case "${OPENJDK_TARGET_CPU}" in @@ -42257,27 +41825,6 @@ $as_echo "$supports" >&6; } - # Check for broken SuSE 'ld' for which 'Only anonymous version tag is allowed in executable.' - USING_BROKEN_SUSE_LD=no - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$GCC" = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken SuSE 'ld' which only understands anonymous version tags in executables" >&5 -$as_echo_n "checking for broken SuSE 'ld' which only understands anonymous version tags in executables... " >&6; } - echo "SUNWprivate_1.1 { local: *; };" > version-script.map - echo "int main() { }" > main.c - if $CXX -Xlinker -version-script=version-script.map main.c 2>&5 >&5; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - USING_BROKEN_SUSE_LD=no - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - USING_BROKEN_SUSE_LD=yes - fi - rm -rf version-script.map main.c a.out - fi - - - # Setup debug symbols (need objcopy from the toolchain for that) # @@ -42343,8 +41890,6 @@ $as_echo "${enable_zip_debug_info}" >&6; } - - ############################################################################### # # Check dependencies for external and internal libraries. @@ -47770,18 +47315,469 @@ fi fi # libCrun is the c++ runtime-library with SunStudio (roughly the equivalent of gcc's libstdc++.so) - if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$LIBCXX" = x; then + if test "x$TOOLCHAIN_TYPE" = xsolstudio && test "x$LIBCXX" = x; then LIBCXX="/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1" fi # TODO better (platform agnostic) test - if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$GCC" = xyes; then + if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$TOOLCHAIN_TYPE" = xgcc; then LIBCXX="-lstdc++" fi + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + + +# Check whether --with-msvcr-dll was given. +if test "${with_msvcr_dll+set}" = set; then : + withval=$with_msvcr_dll; +fi + + + if test "x$with_msvcr_dll" != x; then + # If given explicitely by user, do not probe. If not present, fail directly. + + POSSIBLE_MSVCR_DLL="$with_msvcr_dll" + METHOD="--with-msvcr-dll" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + if test "x$MSVCR_DLL" = x; then + as_fn_error $? "Could not find a proper msvcr100.dll as specified by --with-msvcr-dll" "$LINENO" 5 + fi + fi + + if test "x$MSVCR_DLL" = x; then + # Probe: Using well-known location from Visual Studio 10.0 + if test "x$VCINSTALLDIR" != x; then + CYGWIN_VC_INSTALL_DIR="$VCINSTALLDIR" + + windows_path="$CYGWIN_VC_INSTALL_DIR" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + CYGWIN_VC_INSTALL_DIR="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + CYGWIN_VC_INSTALL_DIR="$unix_path" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + POSSIBLE_MSVCR_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x64/Microsoft.VC100.CRT/msvcr100.dll" + else + POSSIBLE_MSVCR_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x86/Microsoft.VC100.CRT/msvcr100.dll" + fi + + POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + METHOD="well-known location in VCINSTALLDIR" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + fi + fi + + if test "x$MSVCR_DLL" = x; then + # Probe: Check in the Boot JDK directory. + POSSIBLE_MSVCR_DLL="$BOOT_JDK/bin/msvcr100.dll" + + POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + METHOD="well-known location in Boot JDK" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + fi + + if test "x$MSVCR_DLL" = x; then + # Probe: Look in the Windows system32 directory + CYGWIN_SYSTEMROOT="$SYSTEMROOT" + + windows_path="$CYGWIN_SYSTEMROOT" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + CYGWIN_SYSTEMROOT="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + CYGWIN_SYSTEMROOT="$unix_path" + fi + + POSSIBLE_MSVCR_DLL="$CYGWIN_SYSTEMROOT/system32/msvcr100.dll" + + POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + METHOD="well-known location in SYSTEMROOT" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + fi + + if test "x$MSVCR_DLL" = x; then + # Probe: If Visual Studio Express is installed, there is usually one with the debugger + if test "x$VS100COMNTOOLS" != x; then + CYGWIN_VS_TOOLS_DIR="$VS100COMNTOOLS/.." + + windows_path="$CYGWIN_VS_TOOLS_DIR" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + CYGWIN_VS_TOOLS_DIR="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + CYGWIN_VS_TOOLS_DIR="$unix_path" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VS_TOOLS_DIR" -name msvcr100.dll | $GREP -i /x64/ | $HEAD --lines 1` + else + POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VS_TOOLS_DIR" -name msvcr100.dll | $GREP -i /x86/ | $HEAD --lines 1` + fi + + POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + METHOD="search of VS100COMNTOOLS" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + fi + fi + + if test "x$MSVCR_DLL" = x; then + # Probe: Search wildly in the VCINSTALLDIR. We've probably lost by now. + # (This was the original behaviour; kept since it might turn up something) + if test "x$CYGWIN_VC_INSTALL_DIR" != x; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $GREP x64 | $HEAD --lines 1` + else + POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $GREP x86 | $GREP -v ia64 | $GREP -v x64 | $HEAD --lines 1` + if test "x$POSSIBLE_MSVCR_DLL" = x; then + # We're grasping at straws now... + POSSIBLE_MSVCR_DLL=`$FIND "$CYGWIN_VC_INSTALL_DIR" -name msvcr100.dll | $HEAD --lines 1` + fi + fi + + + POSSIBLE_MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + METHOD="search of VCINSTALLDIR" + if test -e "$POSSIBLE_MSVCR_DLL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&5 +$as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} + + # Need to check if the found msvcr is correct architecture + { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 +$as_echo_n "checking found msvcr100.dll architecture... " >&6; } + MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + MSVCR_DLL="$POSSIBLE_MSVCR_DLL" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSVCR_DLL" >&5 +$as_echo "$MSVCR_DLL" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: incorrect, ignoring" >&5 +$as_echo "incorrect, ignoring" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&5 +$as_echo "$as_me: The file type of the located msvcr100.dll is $MSVCR_DLL_FILETYPE" >&6;} + fi + fi + + fi + fi + + if test "x$MSVCR_DLL" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for msvcr100.dll" >&5 +$as_echo_n "checking for msvcr100.dll... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Could not find msvcr100.dll. Please specify using --with-msvcr-dll." "$LINENO" 5 + fi + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$MSVCR_DLL" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of MSVCR_DLL" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + MSVCR_DLL="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MSVCR_DLL to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting MSVCR_DLL to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$MSVCR_DLL" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + MSVCR_DLL="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MSVCR_DLL to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting MSVCR_DLL to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$MSVCR_DLL" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of MSVCR_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + MSVCR_DLL="`cd "$path"; $THEPWDCMD -L`" + fi + + + + +# Check whether --with-dxsdk was given. +if test "${with_dxsdk+set}" = set; then : + withval=$with_dxsdk; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&2;} +fi + + + + +# Check whether --with-dxsdk-lib was given. +if test "${with_dxsdk_lib+set}" = set; then : + withval=$with_dxsdk_lib; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&2;} +fi + + + + +# Check whether --with-dxsdk-include was given. +if test "${with_dxsdk_include+set}" = set; then : + withval=$with_dxsdk_include; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&2;} +fi + + + fi + + ############################################################################### # @@ -48209,7 +48205,7 @@ fi if test "x$ENABLE_PRECOMPH" = xyes; then # Check that the compiler actually supports precomp headers. - if test "x$GCC" = xyes; then + if test "x$TOOLCHAIN_TYPE" = xgcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking that precompiled headers work" >&5 $as_echo_n "checking that precompiled headers work... " >&6; } echo "int alfa();" > conftest.h @@ -49940,8 +49936,9 @@ $CHMOD +x $OUTPUT_ROOT/compare.sh printf "* Environment: $WINDOWS_ENV_VENDOR version $WINDOWS_ENV_VERSION (root at $WINDOWS_ENV_ROOT_PATH)\n" fi printf "* Boot JDK: $BOOT_JDK_VERSION (at $BOOT_JDK)\n" - printf "* C Compiler: $CC_VENDOR version $CC_VERSION (at $CC)\n" - printf "* C++ Compiler: $CXX_VENDOR version $CXX_VERSION (at $CXX)\n" + printf "* Toolchain: $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)\n" + printf "* C Compiler: Version $CC_VERSION_NUMBER (at $CC)\n" + printf "* C++ Compiler: Version $CXX_VERSION_NUMBER (at $CXX)\n" printf "\n" printf "Build performance summary:\n" diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index b24779cf94d..2cad8d6fb39 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -151,6 +151,27 @@ pkgadd_help() { PKGHANDLER_COMMAND="" } +# This function will check if we're called from the "configure" wrapper while +# printing --help. If so, we will print out additional information that can +# only be extracted within the autoconf script, and then exit. This must be +# called at the very beginning in configure.ac. +AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], +[ + if test "x$CONFIGURE_PRINT_TOOLCHAIN_LIST" != x; then + $PRINTF "The following toolchains are available as arguments to --with-toolchain-type.\n" + $PRINTF "Which are valid to use depends on the build platform.\n" + for toolchain in $VALID_TOOLCHAINS_all; do + # Use indirect variable referencing + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" + done + + # And now exit directly + exit 0 + fi +]) + AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], [ # Finally output some useful information to the user @@ -189,8 +210,9 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "* Environment: $WINDOWS_ENV_VENDOR version $WINDOWS_ENV_VERSION (root at $WINDOWS_ENV_ROOT_PATH)\n" fi printf "* Boot JDK: $BOOT_JDK_VERSION (at $BOOT_JDK)\n" - printf "* C Compiler: $CC_VENDOR version $CC_VERSION (at $CC)\n" - printf "* C++ Compiler: $CXX_VENDOR version $CXX_VERSION (at $CXX)\n" + printf "* Toolchain: $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)\n" + printf "* C Compiler: Version $CC_VERSION_NUMBER (at $CC)\n" + printf "* C++ Compiler: Version $CXX_VERSION_NUMBER (at $CXX)\n" printf "\n" printf "Build performance summary:\n" diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in index 25aca388fbe..f7abdd40e0a 100644 --- a/common/autoconf/hotspot-spec.gmk.in +++ b/common/autoconf/hotspot-spec.gmk.in @@ -102,6 +102,8 @@ HOTSPOT_BUILD_JOBS:=$(JOBS) # Control wether Hotspot runs Queens test after building TEST_IN_BUILD=@TEST_IN_BUILD@ +USE_CLANG := @USE_CLANG@ + # For hotspot, override compiler/tools definition to not include FIXPATH prefix. # Hotspot has its own handling on the Windows path situation. CXX:=@CCACHE@ @HOTSPOT_CXX@ diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index f024b7aca82..58d148fe421 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -606,6 +606,4 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], AC_SUBST(ENABLE_DEBUG_SYMBOLS) AC_SUBST(ZIP_DEBUGINFO_FILES) - AC_SUBST(CFLAGS_DEBUG_SYMBOLS) - AC_SUBST(CXXFLAGS_DEBUG_SYMBOLS) ]) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index dccec779cfc..685e9a903c6 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -876,14 +876,25 @@ AC_DEFUN_ONCE([LIB_SETUP_STATIC_LINK_LIBSTDCPP], fi # libCrun is the c++ runtime-library with SunStudio (roughly the equivalent of gcc's libstdc++.so) - if test "x$OPENJDK_TARGET_OS" = xsolaris && test "x$LIBCXX" = x; then + if test "x$TOOLCHAIN_TYPE" = xsolstudio && test "x$LIBCXX" = x; then LIBCXX="/usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libCrun.so.1" fi # TODO better (platform agnostic) test - if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$GCC" = xyes; then + if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$LIBCXX" = x && test "x$TOOLCHAIN_TYPE" = xgcc; then LIBCXX="-lstdc++" fi AC_SUBST(LIBCXX) ]) + +AC_DEFUN_ONCE([LIB_SETUP_ON_WINDOWS], +[ + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + TOOLCHAIN_SETUP_MSVCR_DLL + BASIC_DEPRECATED_ARG_WITH([dxsdk]) + BASIC_DEPRECATED_ARG_WITH([dxsdk-lib]) + BASIC_DEPRECATED_ARG_WITH([dxsdk-include]) + fi + AC_SUBST(MSVCR_DLL) +]) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 5a2f868b823..eef72634234 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -297,11 +297,8 @@ OPENWIN_HOME:=@OPENWIN_HOME@ # The lowest required version of macosx to enforce compatiblity for MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ -# There are two types: CC or CL -# CC is gcc and others behaving reasonably similar. -# CL is cl.exe only. -COMPILER_TYPE:=@COMPILER_TYPE@ -COMPILER_NAME:=@COMPILER_NAME@ +# Toolchain type: gcc, clang, solstudio, lxc, microsoft... +TOOLCHAIN_TYPE:=@TOOLCHAIN_TYPE@ # Option used to tell the compiler whether to create 32- or 64-bit executables COMPILER_TARGET_BITS_FLAG:=@COMPILER_TARGET_BITS_FLAG@ diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 5e7717de024..b7e043fdf6d 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,207 @@ # questions. # +######################################################################## +# This file is responsible for detecting, verifying and setting up the +# toolchain, i.e. the compiler, linker and related utilities. It will setup +# proper paths to the binaries, but it will not setup any flags. +# +# The binaries used is determined by the toolchain type, which is the family of +# compilers and related tools that are used. +######################################################################## + + +# All valid toolchains, regardless of platform (used by help.m4) +VALID_TOOLCHAINS_all="gcc clang solstudio xlc microsoft" + +# These toolchains are valid on different platforms +VALID_TOOLCHAINS_linux="gcc clang" +VALID_TOOLCHAINS_solaris="solstudio" +VALID_TOOLCHAINS_macosx="gcc clang" +VALID_TOOLCHAINS_aix="xlc" +VALID_TOOLCHAINS_windows="microsoft" + +# Toolchain descriptions +TOOLCHAIN_DESCRIPTION_clang="clang/LLVM" +TOOLCHAIN_DESCRIPTION_gcc="GNU Compiler Collection" +TOOLCHAIN_DESCRIPTION_microsoft="Microsoft Visual Studio" +TOOLCHAIN_DESCRIPTION_solstudio="Oracle Solaris Studio" +TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" + +# Setup a number of variables describing how native output files are +# named on this platform/toolchain. +AC_DEFUN([TOOLCHAIN_SETUP_FILENAME_PATTERNS], +[ + # Define filename patterns + if test "x$OPENJDK_TARGET_OS" = xwindows; then + LIBRARY_PREFIX= + SHARED_LIBRARY_SUFFIX='.dll' + STATIC_LIBRARY_SUFFIX='.lib' + SHARED_LIBRARY='[$]1.dll' + STATIC_LIBRARY='[$]1.lib' + OBJ_SUFFIX='.obj' + EXE_SUFFIX='.exe' + else + LIBRARY_PREFIX=lib + SHARED_LIBRARY_SUFFIX='.so' + STATIC_LIBRARY_SUFFIX='.a' + SHARED_LIBRARY='lib[$]1.so' + STATIC_LIBRARY='lib[$]1.a' + OBJ_SUFFIX='.o' + EXE_SUFFIX='' + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + SHARED_LIBRARY='lib[$]1.dylib' + SHARED_LIBRARY_SUFFIX='.dylib' + fi + fi + + AC_SUBST(LIBRARY_PREFIX) + AC_SUBST(SHARED_LIBRARY_SUFFIX) + AC_SUBST(STATIC_LIBRARY_SUFFIX) + AC_SUBST(SHARED_LIBRARY) + AC_SUBST(STATIC_LIBRARY) + AC_SUBST(OBJ_SUFFIX) + AC_SUBST(EXE_SUFFIX) +]) + +# Determine which toolchain type to use, and make sure it is valid for this +# platform. Setup various information about the selected toolchain. +AC_DEFUN_ONCE([TOOLCHAIN_DETERMINE_TOOLCHAIN_TYPE], +[ + AC_ARG_WITH(toolchain-type, [AS_HELP_STRING([--with-toolchain-type], + [the toolchain type (or family) to use, use '--help' to show possible values @<:@platform dependent@:>@])]) + + # Use indirect variable referencing + toolchain_var_name=VALID_TOOLCHAINS_$OPENJDK_BUILD_OS + VALID_TOOLCHAINS=${!toolchain_var_name} + # First toolchain type in the list is the default + DEFAULT_TOOLCHAIN=${VALID_TOOLCHAINS%% *} + + if test "x$with_toolchain_type" = xlist; then + # List all toolchains + AC_MSG_NOTICE([The following toolchains are valid on this platform:]) + for toolchain in $VALID_TOOLCHAINS; do + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$toolchain + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" + done + + exit 0 + elif test "x$with_toolchain_type" != x; then + # User override; check that it is valid + if test "x${VALID_TOOLCHAINS/$with_toolchain_type/}" = "x${VALID_TOOLCHAINS}"; then + AC_MSG_NOTICE([Toolchain type $with_toolchain_type is not valid on this platform.]) + AC_MSG_NOTICE([Valid toolchains: $VALID_TOOLCHAINS.]) + AC_MSG_ERROR([Cannot continue.]) + fi + TOOLCHAIN_TYPE=$with_toolchain_type + else + # No flag given, use default + TOOLCHAIN_TYPE=$DEFAULT_TOOLCHAIN + fi + AC_SUBST(TOOLCHAIN_TYPE) + + TOOLCHAIN_CC_BINARY_clang="clang" + TOOLCHAIN_CC_BINARY_gcc="gcc" + TOOLCHAIN_CC_BINARY_microsoft="cl" + TOOLCHAIN_CC_BINARY_solstudio="cc" + TOOLCHAIN_CC_BINARY_xlc="xlc_r" + + TOOLCHAIN_CXX_BINARY_clang="clang++" + TOOLCHAIN_CXX_BINARY_gcc="g++" + TOOLCHAIN_CXX_BINARY_microsoft="cl" + TOOLCHAIN_CXX_BINARY_solstudio="CC" + TOOLCHAIN_CXX_BINARY_xlc="xlC_r" + + # Use indirect variable referencing + toolchain_var_name=TOOLCHAIN_DESCRIPTION_$TOOLCHAIN_TYPE + TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} + toolchain_var_name=TOOLCHAIN_CC_BINARY_$TOOLCHAIN_TYPE + TOOLCHAIN_CC_BINARY=${!toolchain_var_name} + toolchain_var_name=TOOLCHAIN_CXX_BINARY_$TOOLCHAIN_TYPE + TOOLCHAIN_CXX_BINARY=${!toolchain_var_name} + + TOOLCHAIN_SETUP_FILENAME_PATTERNS + + if test "x$TOOLCHAIN_TYPE" = "x$DEFAULT_TOOLCHAIN"; then + AC_MSG_NOTICE([Using default toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION)]) + else + AC_MSG_NOTICE([Using user selected toolchain $TOOLCHAIN_TYPE ($TOOLCHAIN_DESCRIPTION). Default toolchain is $DEFAULT_TOOLCHAIN.]) + fi +]) + +# Before we start detecting the toolchain executables, we might need some +# special setup, e.g. additional paths etc. +AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION], +[ + # FIXME: Is this needed? + AC_LANG(C++) + + # Store the CFLAGS etc passed to the configure script. + ORG_CFLAGS="$CFLAGS" + ORG_CXXFLAGS="$CXXFLAGS" + ORG_OBJCFLAGS="$OBJCFLAGS" + + # autoconf magic only relies on PATH, so update it if tools dir is specified + OLD_PATH="$PATH" + + # For solaris we really need solaris tools, and not the GNU equivalent. + # The build tools on Solaris reside in /usr/ccs (C Compilation System), + # so add that to path before starting to probe. + # FIXME: This was originally only done for AS,NM,GNM,STRIP,MCS,OBJCOPY,OBJDUMP. + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + PATH="/usr/ccs/bin:$PATH" + fi + + # On Windows, we need to detect the visual studio installation first. + if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then + TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV + fi + + # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to + # override all other locations. + if test "x$TOOLS_DIR" != x; then + PATH=$TOOLS_DIR:$PATH + fi + + # If a devkit is found on the builddeps server, then prepend its path to the + # PATH variable. If there are cross compilers available in the devkit, these + # will be found by AC_PROG_CC et al. + DEVKIT= + BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx, + [ + # Found devkit + PATH="$DEVKIT/bin:$PATH" + SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root" + if test "x$x_includes" = "xNONE"; then + x_includes="$SYS_ROOT/usr/include/X11" + fi + if test "x$x_libraries" = "xNONE"; then + x_libraries="$SYS_ROOT/usr/lib" + fi + ], + []) +]) + +# Restore path, etc +AC_DEFUN_ONCE([TOOLCHAIN_POST_DETECTION], +[ + # Restore old path. + PATH="$OLD_PATH" + + # Restore the flags to the user specified values. + # This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2" + CFLAGS="$ORG_CFLAGS" + CXXFLAGS="$ORG_CXXFLAGS" + OBJCFLAGS="$ORG_OBJCFLAGS" +]) + +# Check if a compiler is of the toolchain type we expect, and save the version +# information from it. If the compiler does not match the expected type, +# this function will abort using AC_MSG_ERROR. If it matches, the version will +# be stored in CC_VERSION_NUMBER/CXX_VERSION_NUMBER (as a dotted number), and +# the full version string in CC_VERSION_STRING/CXX_VERSION_STRING. +# # $1 = compiler to test (CC or CXX) # $2 = human readable name of compiler (C or C++) AC_DEFUN([TOOLCHAIN_CHECK_COMPILER_VERSION], @@ -30,92 +231,112 @@ AC_DEFUN([TOOLCHAIN_CHECK_COMPILER_VERSION], COMPILER=[$]$1 COMPILER_NAME=$2 - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - # Make sure we use the Sun Studio compiler and not gcc on Solaris, which won't work - COMPILER_VERSION_TEST=`$COMPILER -V 2>&1 | $HEAD -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + # cc -V output typically looks like + # cc: Sun C 5.12 Linux_i386 2011/11/16 + COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1` + # Check that this is likely to be the Solaris Studio cc. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null if test $? -ne 0; then - GCC_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - - AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required Sun Studio compiler.]) - AC_MSG_NOTICE([The result from running with -V was: "$COMPILER_VERSION_TEST" and with --version: "$GCC_VERSION_TEST"]) - AC_MSG_ERROR([Sun Studio compiler is required. Try setting --with-tools-dir.]) - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*@<:@ ,\t@:>@$COMPILER_NAME@<:@ ,\t@:>@\(@<:@1-9@:>@\.@<:@0-9@:>@@<:@0-9@:>@*\).*/\1/p"` - COMPILER_VENDOR="Sun Studio" + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.]) + AC_MSG_NOTICE([The result from running with -V was: "$COMPILER_VERSION_OUTPUT"]) + AC_MSG_NOTICE([The result from running with --version was: "$ALT_VERSION_OUTPUT"]) + AC_MSG_ERROR([A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir.]) fi - elif test "x$OPENJDK_TARGET_OS" = xaix; then - COMPILER_VERSION_TEST=`$COMPILER -qversion 2>&1 | $TAIL -n 1` - $ECHO $COMPILER_VERSION_TEST | $GREP "^Version: " > /dev/null - if test $? -ne 0; then - AC_MSG_ERROR([Failed to detect the compiler version of $COMPILER ....]) - else - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n 's/Version: \([0-9][0-9]\.[0-9][0-9]*\).*/\1/p'` - COMPILER_VENDOR='IBM' - fi - elif test "x$OPENJDK_TARGET_OS" = xwindows; then + # Remove usage instructions (if present), and + # collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *@<:@Uu@:>@sage:.*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e "s/^.*@<:@ ,\t@:>@$COMPILER_NAME@<:@ ,\t@:>@\(@<:@1-9@:>@\.@<:@0-9@:>@@<:@0-9@:>@*\).*/\1/"` + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + # xlc -qversion output typically looks like + # IBM XL C/C++ for AIX, V11.1 (5724-X13) + # Version: 11.01.0000.0015 + COMPILER_VERSION_OUTPUT=`$COMPILER -qversion 2>&1` + # Check that this is likely to be the IBM XL C compiler. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "IBM XL C" > /dev/null + if test $? -ne 0; then + ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1` + AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.]) + AC_MSG_NOTICE([The result from running with -qversion was: "$COMPILER_VERSION_OUTPUT"]) + AC_MSG_NOTICE([The result from running with --version was: "$ALT_VERSION_OUTPUT"]) + AC_MSG_ERROR([A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir.]) + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*, V\(@<:@1-9@:>@@<:@0-9.@:>@*\).*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # There is no specific version flag, but all output starts with a version string. # First line typically looks something like: # Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 - COMPILER_VERSION_TEST=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.*Version \(@<:@1-9@:>@@<:@0-9.@:>@*\) .*/\1/p"` - COMPILER_VENDOR="Microsoft CL.EXE" - COMPILER_CPU_TEST=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* for \(.*\)$/\1/p"` - if test "x$OPENJDK_TARGET_CPU" = "xx86"; then - if test "x$COMPILER_CPU_TEST" != "x80x86"; then - AC_MSG_ERROR([Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for "$COMPILER_CPU_TEST"; expected "80x86".]) - fi - elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then - if test "x$COMPILER_CPU_TEST" != "xx64"; then - AC_MSG_ERROR([Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for "$COMPILER_CPU_TEST"; expected "x64".]) - fi - fi - else - COMPILER_VERSION_TEST=`$COMPILER --version 2>&1 | $HEAD -n 1` - # Check that this is likely to be GCC. - $COMPILER --version 2>&1 | $GREP "Free Software Foundation" > /dev/null + COMPILER_VERSION_OUTPUT=`$COMPILER 2>&1 | $HEAD -n 1 | $TR -d '\r'` + # Check that this is likely to be Microsoft CL.EXE. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Microsoft.*Compiler" > /dev/null if test $? -ne 0; then - AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required GCC compiler.]) - AC_MSG_NOTICE([The result from running with --version was: "$COMPILER_VERSION_TEST"]) - AC_MSG_ERROR([GCC compiler is required. Try setting --with-tools-dir.]) + AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.]) + AC_MSG_NOTICE([The result from running it was: "$COMPILER_VERSION_OUTPUT"]) + AC_MSG_ERROR([A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir.]) fi - - # First line typically looks something like: - # gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 - COMPILER_VERSION=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^.* \(@<:@1-9@:>@@<:@0-9.@:>@*\)/\1/p"` - COMPILER_VENDOR=`$ECHO $COMPILER_VERSION_TEST | $SED -n "s/^\(.*\) @<:@1-9@:>@@<:@0-9.@:>@*/\1/p"` + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*ersion.\(@<:@1-9@:>@@<:@0-9.@:>@*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # gcc --version output typically looks like + # gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 + # Copyright (C) 2013 Free Software Foundation, Inc. + # This is free software; see the source for copying conditions. There is NO + # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be GCC. + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "Free Software Foundation" > /dev/null + if test $? -ne 0; then + AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.]) + AC_MSG_NOTICE([The result from running with --version was: "$COMPILER_VERSION"]) + AC_MSG_ERROR([A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir.]) + fi + # Remove Copyright and legalese from version string, and + # collapse into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/ *Copyright .*//'` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.* \(@<:@1-9@:>@\.@<:@0-9.@:>@*\) .*$/\1/'` + elif test "x$TOOLCHAIN_TYPE" = xclang; then + # clang --version output typically looks like + # Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) + # clang version 3.3 (tags/RELEASE_33/final) + # or + # Debian clang version 3.2-7ubuntu1 (tags/RELEASE_32/final) (based on LLVM 3.2) + # Target: x86_64-pc-linux-gnu + # Thread model: posix + COMPILER_VERSION_OUTPUT=`$COMPILER --version 2>&1` + # Check that this is likely to be clang + $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "clang" > /dev/null + if test $? -ne 0; then + AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.]) + AC_MSG_NOTICE([The result from running with --version was: "$COMPILER_VERSION_OUTPUT"]) + AC_MSG_ERROR([A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir.]) + fi + # Collapse compiler output into a single line + COMPILER_VERSION_STRING=`$ECHO $COMPILER_VERSION_OUTPUT` + COMPILER_VERSION_NUMBER=`$ECHO $COMPILER_VERSION_OUTPUT | \ + $SED -e 's/^.*clang version \(@<:@1-9@:>@@<:@0-9.@:>@*\).*$/\1/'` + else + AC_MSG_ERROR([Unknown toolchain type $TOOLCHAIN_TYPE.]) fi - # This sets CC_VERSION or CXX_VERSION. (This comment is a grep marker) - $1_VERSION="$COMPILER_VERSION" - # This sets CC_VENDOR or CXX_VENDOR. (This comment is a grep marker) - $1_VENDOR="$COMPILER_VENDOR" + # This sets CC_VERSION_NUMBER or CXX_VERSION_NUMBER. (This comment is a grep marker) + $1_VERSION_NUMBER="$COMPILER_VERSION_NUMBER" + # This sets CC_VERSION_STRING or CXX_VERSION_STRING. (This comment is a grep marker) + $1_VERSION_STRING="$COMPILER_VERSION_STRING" - AC_MSG_NOTICE([Using $COMPILER_VENDOR $COMPILER_NAME compiler version $COMPILER_VERSION (located at $COMPILER)]) -]) - - -AC_DEFUN_ONCE([TOOLCHAIN_SETUP_SYSROOT_AND_OUT_OPTIONS], -[ - ############################################################################### - # - # Configure the development tool paths and potential sysroot. - # - AC_LANG(C++) - - # The option used to specify the target .o,.a or .so file. - # When compiling, how to specify the to be created object file. - CC_OUT_OPTION='-o$(SPACE)' - # When linking, how to specify the to be created executable. - EXE_OUT_OPTION='-o$(SPACE)' - # When linking, how to specify the to be created dynamically linkable library. - LD_OUT_OPTION='-o$(SPACE)' - # When archiving, how to specify the to be create static archive for object files. - AR_OUT_OPTION='rcs$(SPACE)' - AC_SUBST(CC_OUT_OPTION) - AC_SUBST(EXE_OUT_OPTION) - AC_SUBST(LD_OUT_OPTION) - AC_SUBST(AR_OUT_OPTION) + AC_MSG_NOTICE([Using $TOOLCHAIN_TYPE $COMPILER_NAME compiler version $COMPILER_VERSION_NUMBER @<:@$COMPILER_VERSION_STRING@:>@]) ]) +# Try to locate the given C or C++ compiler in the path, or otherwise. +# # $1 = compiler to test (CC or CXX) # $2 = human readable name of compiler (C or C++) # $3 = list of compiler names to search for @@ -143,10 +364,20 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], fi fi else - # No user supplied value. Locate compiler ourselves + # No user supplied value. Locate compiler ourselves. + + # If we are cross compiling, assume cross compilation tools follows the + # cross compilation standard where they are prefixed with the autoconf + # standard name for the target. For example the binary + # i686-sun-solaris2.10-gcc will cross compile for i686-sun-solaris2.10. + # If we are not cross compiling, then the default compiler name will be + # used. + $1= # If TOOLS_DIR is set, check for all compiler names in there first # before checking the rest of the PATH. + # FIXME: Now that we prefix the TOOLS_DIR to the PATH in the PRE_DETECTION + # step, this should not be necessary. if test -n "$TOOLS_DIR"; then PATH_save="$PATH" PATH="$TOOLS_DIR" @@ -174,6 +405,7 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links # to 'xlc' but it is crucial that we invoke the compiler with the right name! if test "x$OPENJDK_BUILD_OS" != xaix; then + # FIXME: This test should not be needed anymore; we don't do that for any platform. AC_MSG_CHECKING([resolved symbolic links for $1]) BASIC_REMOVE_SYMBOLIC_LINKS(TEST_COMPILER) AC_MSG_RESULT([$TEST_COMPILER]) @@ -208,301 +440,126 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], TOOLCHAIN_CHECK_COMPILER_VERSION([$1], [$COMPILER_NAME]) ]) - -AC_DEFUN([TOOLCHAIN_SETUP_PATHS], +# Detect the core components of the toolchain, i.e. the compilers (CC and CXX), +# preprocessor (CPP and CXXCPP), the linker (LD), the assembler (AS) and the +# archiver (AR). Verify that the compilers are correct according to the +# toolchain type. +AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_CORE], [ - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV - TOOLCHAIN_SETUP_MSVCR_DLL - BASIC_DEPRECATED_ARG_WITH([dxsdk]) - BASIC_DEPRECATED_ARG_WITH([dxsdk-lib]) - BASIC_DEPRECATED_ARG_WITH([dxsdk-include]) - fi - - AC_SUBST(MSVCR_DLL) - - # If --build AND --host is set, then the configure script will find any - # cross compilation tools in the PATH. Cross compilation tools - # follows the cross compilation standard where they are prefixed with ${host}. - # For example the binary i686-sun-solaris2.10-gcc - # will cross compile for i686-sun-solaris2.10 - # If neither of build and host is not set, then build=host and the - # default compiler found in the path will be used. - # Setting only --host, does not seem to be really supported. - # Please set both --build and --host if you want to cross compile. - - if test "x$COMPILE_TYPE" = "xcross"; then - # Now we to find a C/C++ compiler that can build executables for the build - # platform. We can't use the AC_PROG_CC macro, since it can only be used - # once. Also, we need to do this before adding a tools dir to the path, - # otherwise we might pick up cross-compilers which don't use standard naming. - # Otherwise, we'll set the BUILD_tools to the native tools, but that'll have - # to wait until they are properly discovered. - BASIC_PATH_PROGS(BUILD_CC, [cl cc gcc]) - BASIC_FIXUP_EXECUTABLE(BUILD_CC) - BASIC_PATH_PROGS(BUILD_CXX, [cl CC g++]) - BASIC_FIXUP_EXECUTABLE(BUILD_CXX) - BASIC_PATH_PROGS(BUILD_LD, ld) - BASIC_FIXUP_EXECUTABLE(BUILD_LD) - fi - AC_SUBST(BUILD_CC) - AC_SUBST(BUILD_CXX) - AC_SUBST(BUILD_LD) - - # If a devkit is found on the builddeps server, then prepend its path to the - # PATH variable. If there are cross compilers available in the devkit, these - # will be found by AC_PROG_CC et al. - DEVKIT= - BDEPS_CHECK_MODULE(DEVKIT, devkit, xxx, - [ - # Found devkit - PATH="$DEVKIT/bin:$PATH" - SYS_ROOT="$DEVKIT/${rewritten_target}/sys-root" - if test "x$x_includes" = "xNONE"; then - x_includes="$SYS_ROOT/usr/include/X11" - fi - if test "x$x_libraries" = "xNONE"; then - x_libraries="$SYS_ROOT/usr/lib" - fi - ], - []) - - # Store the CFLAGS etal passed to the configure script. - ORG_CFLAGS="$CFLAGS" - ORG_CXXFLAGS="$CXXFLAGS" - ORG_OBJCFLAGS="$OBJCFLAGS" - - # autoconf magic only relies on PATH, so update it if tools dir is specified - OLD_PATH="$PATH" - if test "x$TOOLS_DIR" != x; then - PATH=$TOOLS_DIR:$PATH - fi - - - ### Locate C compiler (CC) - - # On windows, only cl.exe is supported. - # On Solaris, cc is preferred to gcc. - # Elsewhere, gcc is preferred to cc. - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - COMPILER_CHECK_LIST="cl" - elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - COMPILER_CHECK_LIST="cc gcc" - elif test "x$OPENJDK_TARGET_OS" = "xaix"; then - # Do not probe for cc on AIX. - COMPILER_CHECK_LIST="xlc_r" - else - COMPILER_CHECK_LIST="gcc cc" - fi - - TOOLCHAIN_FIND_COMPILER([CC],[C],[$COMPILER_CHECK_LIST]) + # + # Setup the compilers (CC and CXX) + # + TOOLCHAIN_FIND_COMPILER([CC], [C], $TOOLCHAIN_CC_BINARY) # Now that we have resolved CC ourself, let autoconf have its go at it AC_PROG_CC([$CC]) - # Option used to tell the compiler whether to create 32- or 64-bit executables - # Notice that CC contains the full compiler path at this point. - case $CC in - *xlc_r) COMPILER_TARGET_BITS_FLAG="-q";; - *) COMPILER_TARGET_BITS_FLAG="-m";; - esac - AC_SUBST(COMPILER_TARGET_BITS_FLAG) - - ### Locate C++ compiler (CXX) - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - COMPILER_CHECK_LIST="cl" - elif test "x$OPENJDK_TARGET_OS" = "xsolaris"; then - COMPILER_CHECK_LIST="CC g++" - elif test "x$OPENJDK_TARGET_OS" = "xaix"; then - # Do not probe for CC on AIX . - COMPILER_CHECK_LIST="xlC_r" - else - COMPILER_CHECK_LIST="g++ CC" - fi - - TOOLCHAIN_FIND_COMPILER([CXX],[C++],[$COMPILER_CHECK_LIST]) + TOOLCHAIN_FIND_COMPILER([CXX], [C++], $TOOLCHAIN_CXX_BINARY) # Now that we have resolved CXX ourself, let autoconf have its go at it AC_PROG_CXX([$CXX]) - ### Locate other tools + # + # Setup the preprocessor (CPP and CXXCPP) + # + AC_PROG_CPP + BASIC_FIXUP_EXECUTABLE(CPP) + AC_PROG_CXXCPP + BASIC_FIXUP_EXECUTABLE(CXXCPP) - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - AC_PROG_OBJC - BASIC_FIXUP_EXECUTABLE(OBJC) - else - OBJC= - fi - - # Restore the flags to the user specified values. - # This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2" - CFLAGS="$ORG_CFLAGS" - CXXFLAGS="$ORG_CXXFLAGS" - OBJCFLAGS="$ORG_OBJCFLAGS" - - LD="$CC" - LDEXE="$CC" - LDCXX="$CXX" - LDEXECXX="$CXX" - AC_SUBST(LD) - # LDEXE is the linker to use, when creating executables. - AC_SUBST(LDEXE) - # Linking C++ libraries. - AC_SUBST(LDCXX) - # Linking C++ executables. - AC_SUBST(LDEXECXX) - - if test "x$OPENJDK_TARGET_OS" != xwindows; then - BASIC_CHECK_TOOLS(AR, ar) - BASIC_FIXUP_EXECUTABLE(AR) - fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - ARFLAGS="-r" - elif test "x$OPENJDK_TARGET_OS" = xaix; then - ARFLAGS="-X64" - else - ARFLAGS="" - fi - AC_SUBST(ARFLAGS) - - # For hotspot, we need these in Windows mixed path; other platforms keep them the same - HOTSPOT_CXX="$CXX" - HOTSPOT_LD="$LD" - AC_SUBST(HOTSPOT_CXX) - AC_SUBST(HOTSPOT_LD) - - COMPILER_NAME=gcc - COMPILER_TYPE=CC - AS_IF([test "x$OPENJDK_TARGET_OS" = xwindows], [ - # For now, assume that we are always compiling using cl.exe. - CC_OUT_OPTION=-Fo - EXE_OUT_OPTION=-out: - LD_OUT_OPTION=-out: - AR_OUT_OPTION=-out: - # On Windows, reject /usr/bin/link (as determined in CYGWIN_LINK), which is a cygwin - # program for something completely different. - AC_CHECK_PROG([WINLD], [link],[link],,, [$CYGWIN_LINK]) - # Since we must ignore the first found link, WINLD will contain - # the full path to the link.exe program. - BASIC_FIXUP_EXECUTABLE(WINLD) - printf "Windows linker was found at $WINLD\n" + # + # Setup the linker (LD) + # + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # In the Microsoft toolchain we have a separate LD command "link". + # Make sure we reject /usr/bin/link (as determined in CYGWIN_LINK), which is + # a cygwin program for something completely different. + AC_CHECK_PROG([LD], [link],[link],,, [$CYGWIN_LINK]) + BASIC_FIXUP_EXECUTABLE(LD) + # Verify that we indeed succeeded with this trick. AC_MSG_CHECKING([if the found link.exe is actually the Visual Studio linker]) - "$WINLD" --version > /dev/null + "$LD" --version > /dev/null if test $? -eq 0 ; then AC_MSG_RESULT([no]) AC_MSG_ERROR([This is the Cygwin link tool. Please check your PATH and rerun configure.]) else AC_MSG_RESULT([yes]) fi - LD="$WINLD" - LDEXE="$WINLD" - LDCXX="$WINLD" - LDEXECXX="$WINLD" - - AC_CHECK_PROG([MT], [mt], [mt],,, [/usr/bin/mt]) - BASIC_FIXUP_EXECUTABLE(MT) - # The resource compiler - AC_CHECK_PROG([RC], [rc], [rc],,, [/usr/bin/rc]) - BASIC_FIXUP_EXECUTABLE(RC) - - # For hotspot, we need these in Windows mixed path, - # so rewrite them all. Need added .exe suffix. - HOTSPOT_CXX="$CXX.exe" - HOTSPOT_LD="$LD.exe" - HOTSPOT_MT="$MT.exe" - HOTSPOT_RC="$RC.exe" - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_CXX) - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_LD) - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_MT) - BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_RC) - AC_SUBST(HOTSPOT_MT) - AC_SUBST(HOTSPOT_RC) - - RC_FLAGS="-nologo -l 0x409 -r" - AS_IF([test "x$VARIANT" = xOPT], [ - RC_FLAGS="$RC_FLAGS -d NDEBUG" - ]) - - # The version variables used to create RC_FLAGS may be overridden - # in a custom configure script, or possibly the command line. - # Let those variables be expanded at make time in spec.gmk. - # The \$ are escaped to the shell, and the $(...) variables - # are evaluated by make. - RC_FLAGS="$RC_FLAGS \ - -d \"JDK_BUILD_ID=\$(FULL_VERSION)\" \ - -d \"JDK_COMPANY=\$(COMPANY_NAME)\" \ - -d \"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \ - -d \"JDK_VER=\$(JDK_MINOR_VERSION).\$(JDK_MICRO_VERSION).\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0).\$(COOKED_BUILD_NUMBER)\" \ - -d \"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ - -d \"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(JDK_MINOR_VERSION) \$(JDK_UPDATE_META_TAG)\" \ - -d \"JDK_FVER=\$(JDK_MINOR_VERSION),\$(JDK_MICRO_VERSION),\$(if \$(JDK_UPDATE_VERSION),\$(JDK_UPDATE_VERSION),0),\$(COOKED_BUILD_NUMBER)\"" - - # lib.exe is used to create static libraries. - AC_CHECK_PROG([WINAR], [lib],[lib],,,) - BASIC_FIXUP_EXECUTABLE(WINAR) - AR="$WINAR" - ARFLAGS="-nologo -NODEFAULTLIB:MSVCRT" - - AC_CHECK_PROG([DUMPBIN], [dumpbin], [dumpbin],,,) - BASIC_FIXUP_EXECUTABLE(DUMPBIN) - - COMPILER_TYPE=CL - CCXXFLAGS="$CCXXFLAGS -nologo" - ]) - AC_SUBST(RC_FLAGS) - AC_SUBST(COMPILER_TYPE) - - AC_PROG_CPP - BASIC_FIXUP_EXECUTABLE(CPP) - - AC_PROG_CXXCPP - BASIC_FIXUP_EXECUTABLE(CXXCPP) - - if test "x$COMPILE_TYPE" != "xcross"; then - # If we are not cross compiling, use the same compilers for - # building the build platform executables. The cross-compilation - # case needed to be done earlier, but this can only be done after - # the native tools have been localized. - BUILD_CC="$CC" - BUILD_CXX="$CXX" - BUILD_LD="$LD" + LDCXX="$LD" + else + # All other toolchains use the compiler to link. + LD="$CC" + LDCXX="$CXX" fi + AC_SUBST(LD) + # FIXME: it should be CXXLD, according to standard (cf CXXCPP) + AC_SUBST(LDCXX) - # for solaris we really need solaris tools, and not gnu equivalent - # these seems to normally reside in /usr/ccs/bin so add that to path before - # starting to probe # - # NOTE: I add this /usr/ccs/bin after TOOLS but before OLD_PATH - # so that it can be overriden --with-tools-dir - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - PATH="${TOOLS_DIR}:/usr/ccs/bin:${OLD_PATH}" - fi - - # Find the right assembler. + # Setup the assembler (AS) + # if test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: should this really be solaris, or solstudio? BASIC_PATH_PROGS(AS, as) BASIC_FIXUP_EXECUTABLE(AS) else + # FIXME: is this correct for microsoft? AS="$CC -c" fi AC_SUBST(AS) + # + # Setup the archiver (AR) + # + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # The corresponding ar tool is lib.exe (used to create static libraries) + AC_CHECK_PROG([AR], [lib],[lib],,,) + else + BASIC_CHECK_TOOLS(AR, ar) + fi + BASIC_FIXUP_EXECUTABLE(AR) +]) + +# Setup additional tools that is considered a part of the toolchain, but not the +# core part. Many of these are highly platform-specific and do not exist, +# and/or are not needed on all platforms. +AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], +[ + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + AC_PROG_OBJC + BASIC_FIXUP_EXECUTABLE(OBJC) + BASIC_PATH_PROGS(LIPO, lipo) + BASIC_FIXUP_EXECUTABLE(LIPO) + else + OBJC= + fi + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + AC_CHECK_PROG([MT], [mt], [mt],,, [/usr/bin/mt]) + BASIC_FIXUP_EXECUTABLE(MT) + # Setup the resource compiler (RC) + AC_CHECK_PROG([RC], [rc], [rc],,, [/usr/bin/rc]) + BASIC_FIXUP_EXECUTABLE(RC) + AC_CHECK_PROG([DUMPBIN], [dumpbin], [dumpbin],,,) + BASIC_FIXUP_EXECUTABLE(DUMPBIN) + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + BASIC_PATH_PROGS(STRIP, strip) + BASIC_FIXUP_EXECUTABLE(STRIP) BASIC_PATH_PROGS(NM, nm) BASIC_FIXUP_EXECUTABLE(NM) BASIC_PATH_PROGS(GNM, gnm) BASIC_FIXUP_EXECUTABLE(GNM) - BASIC_PATH_PROGS(STRIP, strip) - BASIC_FIXUP_EXECUTABLE(STRIP) + BASIC_PATH_PROGS(MCS, mcs) BASIC_FIXUP_EXECUTABLE(MCS) elif test "x$OPENJDK_TARGET_OS" != xwindows; then + # FIXME: we should unify this with the solaris case above. + BASIC_CHECK_TOOLS(STRIP, strip) + BASIC_FIXUP_EXECUTABLE(STRIP) BASIC_CHECK_TOOLS(NM, nm) BASIC_FIXUP_EXECUTABLE(NM) GNM="$NM" AC_SUBST(GNM) - BASIC_CHECK_TOOLS(STRIP, strip) - BASIC_FIXUP_EXECUTABLE(STRIP) fi # objcopy is used for moving debug symbols to separate files when @@ -517,685 +574,118 @@ AC_DEFUN([TOOLCHAIN_SETUP_PATHS], BASIC_CHECK_TOOLS(OBJDUMP, [gobjdump objdump]) if test "x$OBJDUMP" != x; then - # Only used for compare.sh; we can live without it. BASIC_FIXUP_EXECUTABLE bails if argument is missing. + # Only used for compare.sh; we can live without it. BASIC_FIXUP_EXECUTABLE + # bails if argument is missing. BASIC_FIXUP_EXECUTABLE(OBJDUMP) fi - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - BASIC_PATH_PROGS(LIPO, lipo) - BASIC_FIXUP_EXECUTABLE(LIPO) - fi - - TOOLCHAIN_SETUP_JTREG - - # Restore old path without tools dir - PATH="$OLD_PATH" ]) - -AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_FOR_LIBS], -[ - - ############################################################################### - # - # How to compile shared libraries. - # - - if test "x$GCC" = xyes; then - COMPILER_NAME=gcc - PICFLAG="-fPIC" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib[$]1.so' - STATIC_LIBRARY='lib[$]1.a' - SHARED_LIBRARY_FLAGS="-shared" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='-Xlinker -soname=[$]1' - SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=[$]1' - C_FLAG_REORDER='' - CXX_FLAG_REORDER='' - SET_SHARED_LIBRARY_ORIGIN='-Xlinker -z -Xlinker origin -Xlinker -rpath -Xlinker \$$$$ORIGIN[$]1' - SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN[$]1' - LD="$CC" - LDEXE="$CC" - LDCXX="$CXX" - LDEXECXX="$CXX" - POST_STRIP_CMD="$STRIP -g" - - # Linking is different on MacOSX - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # Might change in the future to clang. - COMPILER_NAME=gcc - SHARED_LIBRARY='lib[$]1.dylib' - SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" - SHARED_LIBRARY_SUFFIX='.dylib' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1' - SET_SHARED_LIBRARY_MAPFILE='' - SET_SHARED_LIBRARY_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.' - SET_EXECUTABLE_ORIGIN="$SET_SHARED_LIBRARY_ORIGIN" - POST_STRIP_CMD="$STRIP -S" - fi +# Setup the build tools (i.e, the compiler and linker used to build programs +# that should be run on the build platform, not the target platform, as a build +# helper). Since the non-cross-compile case uses the normal, target compilers +# for this, we can only do this after these have been setup. +AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], +[ + if test "x$COMPILE_TYPE" = "xcross"; then + # Now we need to find a C/C++ compiler that can build executables for the + # build platform. We can't use the AC_PROG_CC macro, since it can only be + # used once. Also, we need to do this without adding a tools dir to the + # path, otherwise we might pick up cross-compilers which don't use standard + # naming. + + # FIXME: we should list the discovered compilers as an exclude pattern! + # If we do that, we can do this detection before POST_DETECTION, and still + # find the build compilers in the tools dir, if needed. + BASIC_PATH_PROGS(BUILD_CC, [cl cc gcc]) + BASIC_FIXUP_EXECUTABLE(BUILD_CC) + BASIC_PATH_PROGS(BUILD_CXX, [cl CC g++]) + BASIC_FIXUP_EXECUTABLE(BUILD_CXX) + BASIC_PATH_PROGS(BUILD_LD, ld) + BASIC_FIXUP_EXECUTABLE(BUILD_LD) else - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - # If it is not gcc, then assume it is the Oracle Solaris Studio Compiler - COMPILER_NAME=ossc - PICFLAG="-KPIC" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib[$]1.so' - STATIC_LIBRARY='lib[$]1.a' - SHARED_LIBRARY_FLAGS="-G" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='-M[$]1' - C_FLAG_REORDER='-xF' - CXX_FLAG_REORDER='-xF' - SET_SHARED_LIBRARY_ORIGIN='-R\$$$$ORIGIN[$]1' - SET_EXECUTABLE_ORIGIN="$SET_SHARED_LIBRARY_ORIGIN" - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - POST_STRIP_CMD="$STRIP -x" - POST_MCS_CMD="$MCS -d -a \"JDK $FULL_VERSION\"" - fi - if test "x$OPENJDK_TARGET_OS" = xaix; then - COMPILER_NAME=xlc - PICFLAG="-qpic=large" - LIBRARY_PREFIX=lib - SHARED_LIBRARY='lib[$]1.so' - STATIC_LIBRARY='lib[$]1.a' - SHARED_LIBRARY_FLAGS="-qmkshrobj" - SHARED_LIBRARY_SUFFIX='.so' - STATIC_LIBRARY_SUFFIX='.a' - OBJ_SUFFIX='.o' - EXE_SUFFIX='' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='' - C_FLAG_REORDER='' - CXX_FLAG_REORDER='' - SET_SHARED_LIBRARY_ORIGIN='' - SET_EXECUTABLE_ORIGIN="" - CFLAGS_JDK="" - CXXFLAGS_JDK="" - CFLAGS_JDKLIB_EXTRA='' - POST_STRIP_CMD="$STRIP -X32_64" - POST_MCS_CMD="" - fi - if test "x$OPENJDK_TARGET_OS" = xwindows; then - # If it is not gcc, then assume it is the MS Visual Studio compiler - COMPILER_NAME=cl - PICFLAG="" - LIBRARY_PREFIX= - SHARED_LIBRARY='[$]1.dll' - STATIC_LIBRARY='[$]1.lib' - SHARED_LIBRARY_FLAGS="-LD" - SHARED_LIBRARY_SUFFIX='.dll' - STATIC_LIBRARY_SUFFIX='.lib' - OBJ_SUFFIX='.obj' - EXE_SUFFIX='.exe' - SET_SHARED_LIBRARY_NAME='' - SET_SHARED_LIBRARY_MAPFILE='' - SET_SHARED_LIBRARY_ORIGIN='' - SET_EXECUTABLE_ORIGIN='' - fi + # If we are not cross compiling, use the normal target compilers for + # building the build platform executables. + BUILD_CC="$CC" + BUILD_CXX="$CXX" + BUILD_LD="$LD" fi - AC_SUBST(COMPILER_NAME) - AC_SUBST(OBJ_SUFFIX) - AC_SUBST(SHARED_LIBRARY) - AC_SUBST(STATIC_LIBRARY) - AC_SUBST(LIBRARY_PREFIX) - AC_SUBST(SHARED_LIBRARY_SUFFIX) - AC_SUBST(STATIC_LIBRARY_SUFFIX) - AC_SUBST(EXE_SUFFIX) - AC_SUBST(SHARED_LIBRARY_FLAGS) - AC_SUBST(SET_SHARED_LIBRARY_NAME) - AC_SUBST(SET_SHARED_LIBRARY_MAPFILE) - AC_SUBST(C_FLAG_REORDER) - AC_SUBST(CXX_FLAG_REORDER) - AC_SUBST(SET_SHARED_LIBRARY_ORIGIN) - AC_SUBST(SET_EXECUTABLE_ORIGIN) - AC_SUBST(POST_STRIP_CMD) - AC_SUBST(POST_MCS_CMD) - - # The (cross) compiler is now configured, we can now test capabilities - # of the target platform. + AC_SUBST(BUILD_CC) + AC_SUBST(BUILD_CXX) + AC_SUBST(BUILD_LD) ]) -AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], +# Setup legacy variables that are still needed as alternative ways to refer to +# parts of the toolchain. +AC_DEFUN_ONCE([TOOLCHAIN_SETUP_LEGACY], [ - - ############################################################################### - # - # Setup the opt flags for different compilers - # and different operating systems. - # - - # - # NOTE: check for -mstackrealign needs to be below potential addition of -m32 - # - if test "x$OPENJDK_TARGET_CPU_BITS" = x32 && test "x$OPENJDK_TARGET_OS" = xmacosx; then - # On 32-bit MacOSX the OS requires C-entry points to be 16 byte aligned. - # While waiting for a better solution, the current workaround is to use -mstackrealign. - CFLAGS="$CFLAGS -mstackrealign" - AC_MSG_CHECKING([if 32-bit compiler supports -mstackrealign]) - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - AC_MSG_ERROR([The selected compiler $CXX does not support -mstackrealign! Try to put another compiler in the path.]) - ] - ) + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # For hotspot, we need these in Windows mixed path, + # so rewrite them all. Need added .exe suffix. + HOTSPOT_CXX="$CXX.exe" + HOTSPOT_LD="$LD.exe" + HOTSPOT_MT="$MT.exe" + HOTSPOT_RC="$RC.exe" + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_CXX) + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_LD) + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_MT) + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_RC) + AC_SUBST(HOTSPOT_MT) + AC_SUBST(HOTSPOT_RC) + else + HOTSPOT_CXX="$CXX" + HOTSPOT_LD="$LD" fi + AC_SUBST(HOTSPOT_CXX) + AC_SUBST(HOTSPOT_LD) - C_FLAG_DEPS="-MMD -MF" - CXX_FLAG_DEPS="-MMD -MF" - - case $COMPILER_TYPE in - CC ) - case $COMPILER_NAME in - gcc ) - case $OPENJDK_TARGET_OS in - macosx ) - # On MacOSX we optimize for size, something - # we should do for all platforms? - C_O_FLAG_HI="-Os" - C_O_FLAG_NORM="-Os" - C_O_FLAG_NONE="" - ;; - *) - C_O_FLAG_HI="-O3" - C_O_FLAG_NORM="-O2" - C_O_FLAG_NONE="-O0" - ;; - esac - CXX_O_FLAG_HI="$C_O_FLAG_HI" - CXX_O_FLAG_NORM="$C_O_FLAG_NORM" - CXX_O_FLAG_NONE="$C_O_FLAG_NONE" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" && test "x$DEBUG_LEVEL" = "xfastdebug"; then - CFLAGS_DEBUG_SYMBOLS="-g1" - CXXFLAGS_DEBUG_SYMBOLS="-g1" - fi - ;; - ossc ) - # - # Forte has different names for this with their C++ compiler... - # - C_FLAG_DEPS="-xMMD -xMF" - CXX_FLAG_DEPS="-xMMD -xMF" - - # Extra options used with HIGHEST - # - # WARNING: Use of OPTIMIZATION_LEVEL=HIGHEST in your Makefile needs to be - # done with care, there are some assumptions below that need to - # be understood about the use of pointers, and IEEE behavior. - # - # Use non-standard floating point mode (not IEEE 754) - CC_HIGHEST="$CC_HIGHEST -fns" - # Do some simplification of floating point arithmetic (not IEEE 754) - CC_HIGHEST="$CC_HIGHEST -fsimple" - # Use single precision floating point with 'float' - CC_HIGHEST="$CC_HIGHEST -fsingle" - # Assume memory references via basic pointer types do not alias - # (Source with excessing pointer casting and data access with mixed - # pointer types are not recommended) - CC_HIGHEST="$CC_HIGHEST -xalias_level=basic" - # Use intrinsic or inline versions for math/std functions - # (If you expect perfect errno behavior, do not use this) - CC_HIGHEST="$CC_HIGHEST -xbuiltin=%all" - # Loop data dependency optimizations (need -xO3 or higher) - CC_HIGHEST="$CC_HIGHEST -xdepend" - # Pointer parameters to functions do not overlap - # (Similar to -xalias_level=basic usage, but less obvious sometimes. - # If you pass in multiple pointers to the same data, do not use this) - CC_HIGHEST="$CC_HIGHEST -xrestrict" - # Inline some library routines - # (If you expect perfect errno behavior, do not use this) - CC_HIGHEST="$CC_HIGHEST -xlibmil" - # Use optimized math routines - # (If you expect perfect errno behavior, do not use this) - # Can cause undefined external on Solaris 8 X86 on __sincos, removing for now - #CC_HIGHEST="$CC_HIGHEST -xlibmopt" - - if test "x$OPENJDK_TARGET_CPU" = xsparc; then - CFLAGS_JDK="${CFLAGS_JDK} -xmemalign=4s" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -xmemalign=4s" - fi - - case $OPENJDK_TARGET_CPU_ARCH in - x86) - C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xregs=no%frameptr" - C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" - C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" - C_O_FLAG_NONE="-xregs=no%frameptr" - CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" - CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" - CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" - CXX_O_FLAG_NONE="-xregs=no%frameptr" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" - CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" - fi - ;; - sparc) - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" - C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" - C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" - C_O_FLAG_NONE="" - CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" - CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" - CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" - CXX_O_FLAG_NONE="" - ;; - esac - - CFLAGS_DEBUG_SYMBOLS="-g -xs" - CXXFLAGS_DEBUG_SYMBOLS="-g0 -xs" - ;; - xlc ) - C_FLAG_DEPS="-qmakedep=gcc -MF" - CXX_FLAG_DEPS="-qmakedep=gcc -MF" - C_O_FLAG_HIGHEST="-O3" - C_O_FLAG_HI="-O3 -qstrict" - C_O_FLAG_NORM="-O2" - C_O_FLAG_NONE="" - CXX_O_FLAG_HIGHEST="-O3" - CXX_O_FLAG_HI="-O3 -qstrict" - CXX_O_FLAG_NORM="-O2" - CXX_O_FLAG_NONE="" - CFLAGS_DEBUG_SYMBOLS="-g" - CXXFLAGS_DEBUG_SYMBOLS="-g" - LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall" - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt" - ;; - esac - ;; - CL ) - C_O_FLAG_HIGHEST="-O2" - C_O_FLAG_HI="-O1" - C_O_FLAG_NORM="-O1" - C_O_FLAG_NONE="-Od" - CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" - CXX_O_FLAG_HI="$C_O_FLAG_HI" - CXX_O_FLAG_NORM="$C_O_FLAG_NORM" - CXX_O_FLAG_NONE="$C_O_FLAG_NONE" - ;; - esac - - if test -z "$C_O_FLAG_HIGHEST"; then - C_O_FLAG_HIGHEST="$C_O_FLAG_HI" + if test "x$TOOLCHAIN_TYPE" = xclang; then + USE_CLANG=true fi + AC_SUBST(USE_CLANG) - if test -z "$CXX_O_FLAG_HIGHEST"; then - CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HI" - fi - - AC_SUBST(C_O_FLAG_HIGHEST) - AC_SUBST(C_O_FLAG_HI) - AC_SUBST(C_O_FLAG_NORM) - AC_SUBST(C_O_FLAG_NONE) - AC_SUBST(CXX_O_FLAG_HIGHEST) - AC_SUBST(CXX_O_FLAG_HI) - AC_SUBST(CXX_O_FLAG_NORM) - AC_SUBST(CXX_O_FLAG_NONE) - AC_SUBST(C_FLAG_DEPS) - AC_SUBST(CXX_FLAG_DEPS) + # LDEXE is the linker to use, when creating executables. Not really used. + # FIXME: These should just be removed! + LDEXE="$LD" + LDEXECXX="$LDCXX" + AC_SUBST(LDEXE) + AC_SUBST(LDEXECXX) ]) -AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_FOR_JDK], +# Do some additional checks on the detected tools. +AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS], [ - - if test "x$CFLAGS" != "x${ADDED_CFLAGS}"; then - AC_MSG_WARN([Ignoring CFLAGS($CFLAGS) found in environment. Use --with-extra-cflags]) - fi - - if test "x$CXXFLAGS" != "x${ADDED_CXXFLAGS}"; then - AC_MSG_WARN([Ignoring CXXFLAGS($CXXFLAGS) found in environment. Use --with-extra-cxxflags]) - fi - - if test "x$LDFLAGS" != "x${ADDED_LDFLAGS}"; then - AC_MSG_WARN([Ignoring LDFLAGS($LDFLAGS) found in environment. Use --with-extra-ldflags]) - fi - - AC_ARG_WITH(extra-cflags, [AS_HELP_STRING([--with-extra-cflags], - [extra flags to be used when compiling jdk c-files])]) - - AC_ARG_WITH(extra-cxxflags, [AS_HELP_STRING([--with-extra-cxxflags], - [extra flags to be used when compiling jdk c++-files])]) - - AC_ARG_WITH(extra-ldflags, [AS_HELP_STRING([--with-extra-ldflags], - [extra flags to be used when linking jdk])]) - - CFLAGS_JDK="${CFLAGS_JDK} $with_extra_cflags" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $with_extra_cxxflags" - LDFLAGS_JDK="${LDFLAGS_JDK} $with_extra_ldflags" - - # Hotspot needs these set in their legacy form - LEGACY_EXTRA_CFLAGS=$with_extra_cflags - LEGACY_EXTRA_CXXFLAGS=$with_extra_cxxflags - LEGACY_EXTRA_LDFLAGS=$with_extra_ldflags - - AC_SUBST(LEGACY_EXTRA_CFLAGS) - AC_SUBST(LEGACY_EXTRA_CXXFLAGS) - AC_SUBST(LEGACY_EXTRA_LDFLAGS) - - ############################################################################### - # - # Now setup the CFLAGS and LDFLAGS for the JDK build. - # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. - # - case $COMPILER_NAME in - gcc ) - # these options are used for both C and C++ compiles - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Wall -Wno-parentheses -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe \ - -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - arm ) - # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - ppc ) - # on ppc we don't prevent gcc to omit frame pointer nor strict-aliasing - ;; - * ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - ;; - ossc ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" - case $OPENJDK_TARGET_CPU_ARCH in - x86 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" - CFLAGS_JDK="$CFLAGS_JDK -erroff=E_BAD_PRAGMA_PACK_VALUE" - ;; - esac - - CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" - CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" - - LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib" - ;; - xlc ) - CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - - LDFLAGS_JDK="$LDFLAGS_JDK" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK" - ;; - cl ) - CCXXFLAGS_JDK="$CCXXFLAGS $CCXXFLAGS_JDK -Zi -MD -Zc:wchar_t- -W3 -wd4800 \ - -D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB -DWIN32_LEAN_AND_MEAN \ - -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ - -DWIN32 -DIAL" - case $OPENJDK_TARGET_CPU in - x86 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_X86_ -Dx86" - ;; - x86_64 ) - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_AMD64_ -Damd64" - ;; - esac - ;; - esac - - ############################################################################### - - # Adjust flags according to debug level. - case $DEBUG_LEVEL in - fastdebug ) - CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" - CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" - C_O_FLAG_HI="$C_O_FLAG_NORM" - C_O_FLAG_NORM="$C_O_FLAG_NORM" - CXX_O_FLAG_HI="$CXX_O_FLAG_NORM" - CXX_O_FLAG_NORM="$CXX_O_FLAG_NORM" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - slowdebug ) - CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS" - CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS" - C_O_FLAG_HI="$C_O_FLAG_NONE" - C_O_FLAG_NORM="$C_O_FLAG_NONE" - CXX_O_FLAG_HI="$CXX_O_FLAG_NONE" - CXX_O_FLAG_NORM="$CXX_O_FLAG_NONE" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - esac - - CCXXFLAGS_JDK="$CCXXFLAGS_JDK $ADD_LP64" - # The package path is used only on macosx? + # FIXME: clean this up, and/or move it elsewhere. PACKAGE_PATH=/opt/local AC_SUBST(PACKAGE_PATH) - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then - # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the - # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN - # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). - # Note: -Dmacro is the same as #define macro 1 - # -Dmacro= is the same as #define macro - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" - else - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_LITTLE_ENDIAN" - fi - else - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -D_BIG_ENDIAN" - fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DLINUX" - fi - if test "x$OPENJDK_TARGET_OS" = xwindows; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DWINDOWS" - fi - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DSOLARIS" - fi - if test "x$OPENJDK_TARGET_OS" = xaix; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DAIX -DPPC64" - fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMACOSX -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" - # Setting these parameters makes it an error to link to macosx APIs that are - # newer than the given OS version and makes the linked binaries compatible even - # if built on a newer version of the OS. - # The expected format is X.Y.Z - MACOSX_VERSION_MIN=10.7.0 - AC_SUBST(MACOSX_VERSION_MIN) - # The macro takes the version with no dots, ex: 1070 - # Let the flags variables get resolved in make for easier override on make - # command line. - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - fi - if test "x$OPENJDK_TARGET_OS" = xbsd; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DBSD -D_ALLBSD_SOURCE" - fi - if test "x$DEBUG_LEVEL" = xrelease; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DNDEBUG" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DTRIMMED" - fi - else - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DDEBUG" - fi - - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DRELEASE='\"\$(RELEASE)\"'" - - CCXXFLAGS_JDK="$CCXXFLAGS_JDK \ - -I${JDK_OUTPUTDIR}/include \ - -I${JDK_OUTPUTDIR}/include/$OPENJDK_TARGET_OS \ - -I${JDK_TOPDIR}/src/share/javavm/export \ - -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_EXPORT_DIR/javavm/export \ - -I${JDK_TOPDIR}/src/share/native/common \ - -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_API_DIR/native/common" - - # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA " - - # Executable flags - CFLAGS_JDKEXE="$CCXXFLAGS_JDK $CFLAGS_JDK" - CXXFLAGS_JDKEXE="$CCXXFLAGS_JDK $CXXFLAGS_JDK" - - # Now this is odd. The JDK native libraries have to link against libjvm.so - # On 32-bit machines there is normally two distinct libjvm.so:s, client and server. - # Which should we link to? Are we lucky enough that the binary api to the libjvm.so library - # is identical for client and server? Yes. Which is picked at runtime (client or server)? - # Neither, since the chosen libjvm.so has already been loaded by the launcher, all the following - # libraries will link to whatever is in memory. Yuck. - # - # Thus we offer the compiler to find libjvm.so first in server then in client. It works. Ugh. - if test "x$COMPILER_NAME" = xcl; then - LDFLAGS_JDK="$LDFLAGS_JDK -nologo -opt:ref -incremental:no" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - LDFLAGS_JDK="$LDFLAGS_JDK -safeseh" - fi - # TODO: make -debug optional "--disable-full-debug-symbols" - LDFLAGS_JDK="$LDFLAGS_JDK -debug" - LDFLAGS_JDKLIB="${LDFLAGS_JDK} -dll -libpath:${JDK_OUTPUTDIR}/lib" - LDFLAGS_JDKLIB_SUFFIX="" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then - LDFLAGS_STACK_SIZE=1048576 - else - LDFLAGS_STACK_SIZE=327680 - fi - LDFLAGS_JDKEXE="${LDFLAGS_JDK} /STACK:$LDFLAGS_STACK_SIZE" - else - if test "x$COMPILER_NAME" = xgcc; then - # If this is a --hash-style=gnu system, use --hash-style=both, why? - HAS_GNU_HASH=`$CC -dumpspecs 2>/dev/null | $GREP 'hash-style=gnu'` - if test -n "$HAS_GNU_HASH"; then - LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker --hash-style=both " + # Check for extra potential brokenness. + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + # On Windows, double-check that we got the right compiler. + CC_VERSION_OUTPUT=`$CC 2>&1 | $HEAD -n 1 | $TR -d '\r'` + COMPILER_CPU_TEST=`$ECHO $CC_VERSION_OUTPUT | $SED -n "s/^.* \(.*\)$/\1/p"` + if test "x$OPENJDK_TARGET_CPU" = "xx86"; then + if test "x$COMPILER_CPU_TEST" != "x80x86"; then + AC_MSG_ERROR([Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for "$COMPILER_CPU_TEST"; expected "80x86".]) fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then - # And since we now know that the linker is gnu, then add -z defs, to forbid - # undefined symbols in object files. - LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -z -Xlinker defs" - if test "x$DEBUG_LEVEL" = "xrelease"; then - # When building release libraries, tell the linker optimize them. - # Should this be supplied to the OSS linker as well? - LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -O1" - fi + elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + if test "x$COMPILER_CPU_TEST" != "xx64"; then + AC_MSG_ERROR([Target CPU mismatch. We are building for $OPENJDK_TARGET_CPU but CL is for "$COMPILER_CPU_TEST"; expected "x64".]) fi fi - LDFLAGS_JDKLIB="${LDFLAGS_JDK} $SHARED_LIBRARY_FLAGS \ - -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}" - - # On some platforms (mac) the linker warns about non existing -L dirs. - # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. - # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/minimal" - else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server" - fi - - LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm" - if test "x$COMPILER_NAME" = xossc; then - LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc" - fi - - LDFLAGS_JDKEXE="${LDFLAGS_JDK}" - if test "x$OPENJDK_TARGET_OS" = xlinux; then - LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Xlinker --allow-shlib-undefined" - fi fi - AC_SUBST(CFLAGS_JDKLIB) - AC_SUBST(CFLAGS_JDKEXE) - - AC_SUBST(CXXFLAGS_JDKLIB) - AC_SUBST(CXXFLAGS_JDKEXE) - - AC_SUBST(LDFLAGS_JDKLIB) - AC_SUBST(LDFLAGS_JDKEXE) - AC_SUBST(LDFLAGS_JDKLIB_SUFFIX) - AC_SUBST(LDFLAGS_JDKEXE_SUFFIX) - AC_SUBST(LDFLAGS_CXX_JDK) -]) - - -# TOOLCHAIN_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE], -# [RUN-IF-FALSE]) -# ------------------------------------------------------------ -# Check that the c and c++ compilers support an argument -AC_DEFUN([TOOLCHAIN_COMPILER_CHECK_ARGUMENTS], -[ - AC_MSG_CHECKING([if compiler supports "$1"]) - supports=yes - - saved_cflags="$CFLAGS" - CFLAGS="$CFLAGS $1" - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [], - [supports=no]) - AC_LANG_POP([C]) - CFLAGS="$saved_cflags" - - saved_cxxflags="$CXXFLAGS" - CXXFLAGS="$CXXFLAG $1" - AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int i;]])], [], - [supports=no]) - AC_LANG_POP([C++]) - CXXFLAGS="$saved_cxxflags" - - AC_MSG_RESULT([$supports]) - if test "x$supports" = "xyes" ; then - m4_ifval([$2], [$2], [:]) - else - m4_ifval([$3], [$3], [:]) + if test "x$TOOLCHAIN_TYPE" = xgcc; then + # If this is a --hash-style=gnu system, use --hash-style=both, why? + HAS_GNU_HASH=`$CC -dumpspecs 2>/dev/null | $GREP 'hash-style=gnu'` + # This is later checked when setting flags. fi -]) -AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_MISC], -[ - # Some Zero and Shark settings. - # ZERO_ARCHFLAG tells the compiler which mode to build for - case "${OPENJDK_TARGET_CPU}" in - s390) - ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}31" - ;; - *) - ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" - esac - TOOLCHAIN_COMPILER_CHECK_ARGUMENTS([$ZERO_ARCHFLAG], [], [ZERO_ARCHFLAG=""]) - AC_SUBST(ZERO_ARCHFLAG) - - # Check that the compiler supports -mX (or -qX on AIX) flags - # Set COMPILER_SUPPORTS_TARGET_BITS_FLAG to 'true' if it does - TOOLCHAIN_COMPILER_CHECK_ARGUMENTS([${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}], - [COMPILER_SUPPORTS_TARGET_BITS_FLAG=true], - [COMPILER_SUPPORTS_TARGET_BITS_FLAG=false]) - AC_SUBST(COMPILER_SUPPORTS_TARGET_BITS_FLAG) - - - # Check for broken SuSE 'ld' for which 'Only anonymous version tag is allowed in executable.' + # Check for broken SuSE 'ld' for which 'Only anonymous version tag is allowed + # in executable.' USING_BROKEN_SUSE_LD=no - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$GCC" = xyes; then + if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$TOOLCHAIN_TYPE" = xgcc; then AC_MSG_CHECKING([for broken SuSE 'ld' which only understands anonymous version tags in executables]) echo "SUNWprivate_1.1 { local: *; };" > version-script.map echo "int main() { }" > main.c @@ -1211,7 +701,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_COMPILER_FLAGS_MISC], AC_SUBST(USING_BROKEN_SUSE_LD) ]) -# Setup the JTREG paths +# Setup the JTReg Regression Test Harness. AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], [ AC_ARG_WITH(jtreg, [AS_HELP_STRING([--with-jtreg], diff --git a/make/Main.gmk b/make/Main.gmk index b13903aa23d..57c265fd8d6 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -243,7 +243,7 @@ reconfigure: else @$(ECHO) "Re-running configure using default settings" endif - @( cd $(OUTPUT_ROOT) && $(BASH) $(TOPDIR)/configure "$(CONFIGURE_COMMAND_LINE)" ) + @( cd $(OUTPUT_ROOT) && $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) ) .PHONY: langtools corba jaxp jaxws hotspot jdk nashorn images overlay-images install test docs .PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only nashorn-only images-only overlay-images-only install-only test-only docs-only diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 0c1f7df044e..361ea8d4c13 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ ifeq (,$(_MAKEBASE_GMK)) $(error You must include MakeBase.gmk prior to including NativeCompilation.gmk) endif -ifeq ($(COMPILER_TYPE),CC) +ifneq ($(TOOLCHAIN_TYPE), microsoft) COMPILING_MSG=echo $(LOG_INFO) "Compiling $(notdir $1) (for $(notdir $2))" LINKING_MSG=echo $(LOG_INFO) "Linking $1" LINKING_EXE_MSG=echo $(LOG_INFO) "Linking executable $1" @@ -86,18 +86,18 @@ define add_native_source # Include previously generated dependency information. (if it exists) -include $$($1_$2_DEP) - ifeq ($(COMPILER_TYPE),CL) + ifeq ($(TOOLCHAIN_TYPE), microsoft) $1_$2_DEBUG_OUT_FLAGS:=-Fd$$(patsubst %$(OBJ_SUFFIX),%.pdb,$$($1_$2_OBJ)) \ -Fm$$(patsubst %$(OBJ_SUFFIX),%.map,$$($1_$2_OBJ)) endif endif $$($1_$2_OBJ) : $2 - ifeq ($(COMPILER_TYPE),CC) + ifneq ($(TOOLCHAIN_TYPE), microsoft) $$(call COMPILING_MSG,$2,$$($1_TARGET)) - # The Sun studio compiler doesn't output the full path to the object file in the + # The Solaris studio compiler doesn't output the full path to the object file in the # generated deps files. Fixing it with sed. If compiling assembly, don't try this. - ifeq ($(COMPILER_NAME)$$(filter %.s,$2),ossc) + ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio) $$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 $(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP) else @@ -107,7 +107,7 @@ define add_native_source # The Visual Studio compiler lacks a feature for generating make dependencies, but by # setting -showIncludes, all included files are printed. These are filtered out and # parsed into make dependences. - ifeq ($(COMPILER_TYPE),CL) + ifeq ($(TOOLCHAIN_TYPE), microsoft) ($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \ $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \ | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v "^Note: including file:" \ From e00f753d87153b526844946e15e4d5377a191a41 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 24 Feb 2014 13:29:26 +0100 Subject: [PATCH 186/265] 8035495: Improvements in autoconf integration Reviewed-by: mduigou, tbell --- common/autoconf/Makefile.in | 4 +- common/autoconf/autogen.sh | 42 ++-- common/autoconf/basics.m4 | 32 +-- common/autoconf/compare.sh.in | 4 +- common/autoconf/configure | 23 +- common/autoconf/configure.ac | 2 +- common/autoconf/generated-configure.sh | 278 +++++++++++++------------ common/autoconf/spec.gmk.in | 11 +- configure | 9 +- 9 files changed, 230 insertions(+), 175 deletions(-) diff --git a/common/autoconf/Makefile.in b/common/autoconf/Makefile.in index 000a9e73aa7..6e47fe9eb19 100644 --- a/common/autoconf/Makefile.in +++ b/common/autoconf/Makefile.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,4 +24,4 @@ # This Makefile was generated by configure @DATE_WHEN_CONFIGURED@ # GENERATED FILE, DO NOT EDIT SPEC:=@OUTPUT_ROOT@/spec.gmk -include @SRC_ROOT@/Makefile +include @TOPDIR@/Makefile diff --git a/common/autoconf/autogen.sh b/common/autoconf/autogen.sh index 162f27833cf..d1d8a0df165 100644 --- a/common/autoconf/autogen.sh +++ b/common/autoconf/autogen.sh @@ -22,6 +22,23 @@ # questions. # +generate_configure_script() { + # First create a header + cat > $1 << EOT +#!/bin/bash +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +EOT + # Then replace "magic" variables in configure.ac and append the output + # from autoconf. $2 is either cat (just a no-op) or a filter. + cat $script_dir/configure.ac | sed -e "s|@DATE_WHEN_GENERATED@|$TIMESTAMP|" | \ + eval $2 | ${AUTOCONF} -W all -I$script_dir - >> $1 + rm -rf autom4te.cache +} + script_dir=`dirname $0` # Create a timestamp as seconds since epoch @@ -36,7 +53,8 @@ else fi if test "x$CUSTOM_CONFIG_DIR" = "x"; then - custom_script_dir="$script_dir/../../closed/autoconf" + topdir=`cd $script_dir/../.. >/dev/null && pwd` + custom_script_dir="$topdir/closed/autoconf" else custom_script_dir=$CUSTOM_CONFIG_DIR fi @@ -45,25 +63,23 @@ custom_hook=$custom_script_dir/custom-hook.m4 AUTOCONF="`which autoconf 2> /dev/null | grep -v '^no autoconf in'`" -echo "Autoconf found: ${AUTOCONF}" - if test "x${AUTOCONF}" = x; then - echo You need autoconf installed to be able to regenerate the configure script - echo Error: Cannot find autoconf 1>&2 + echo "You need autoconf installed to be able to regenerate the configure script" + echo "Error: Cannot find autoconf" 1>&2 exit 1 fi -echo Generating generated-configure.sh with ${AUTOCONF} -cat $script_dir/configure.ac | sed -e "s|@DATE_WHEN_GENERATED@|$TIMESTAMP|" | ${AUTOCONF} -W all -I$script_dir - > $script_dir/generated-configure.sh -rm -rf autom4te.cache +autoconf_version=`$AUTOCONF --version | head -1` +echo "Using autoconf at ${AUTOCONF} [$autoconf_version]" + +echo "Generating generated-configure.sh" +generate_configure_script "$script_dir/generated-configure.sh" 'cat' if test -e $custom_hook; then - echo Generating custom generated-configure.sh # We have custom sources available; also generate configure script # with custom hooks compiled in. - cat $script_dir/configure.ac | sed -e "s|@DATE_WHEN_GENERATED@|$TIMESTAMP|" | \ - sed -e "s|#CUSTOM_AUTOCONF_INCLUDE|m4_include([$custom_hook])|" | ${AUTOCONF} -W all -I$script_dir - > $custom_script_dir/generated-configure.sh - rm -rf autom4te.cache + echo "Generating custom generated-configure.sh" + generate_configure_script "$custom_script_dir/generated-configure.sh" 'sed -e "s|#CUSTOM_AUTOCONF_INCLUDE|m4_include([$custom_hook])|"' else - echo No custom hook found: $custom_hook + echo "(No custom hook found at $custom_hook)" fi diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 16e33447c3f..092c9596937 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -418,14 +418,21 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], # Setup basic configuration paths, and platform-specific stuff related to PATHs. AC_DEFUN_ONCE([BASIC_SETUP_PATHS], [ - # Locate the directory of this script. - SCRIPT="[$]0" - AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD -L` + # We get the top-level directory from the supporting wrappers. + AC_MSG_CHECKING([for top-level directory]) + AC_MSG_RESULT([$TOPDIR]) + BASIC_FIXUP_PATH(TOPDIR) + AC_SUBST(TOPDIR) - # Where is the source? It is located two levels above the configure script. + # SRC_ROOT is a traditional alias for TOPDIR. + SRC_ROOT=$TOPDIR + + # Locate the directory of this script. + AUTOCONF_DIR=$TOPDIR/common/autoconf + + # Save the current directory this script was started from CURDIR="$PWD" - cd "$AUTOCONF_DIR/../.." - SRC_ROOT="`$THEPWDCMD -L`" + BASIC_FIXUP_PATH(CURDIR) if test "x$OPENJDK_TARGET_OS" = "xwindows"; then PATH_SEP=";" @@ -433,13 +440,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS], else PATH_SEP=":" fi - - AC_SUBST(SRC_ROOT) AC_SUBST(PATH_SEP) - cd "$CURDIR" - - BASIC_FIXUP_PATH(SRC_ROOT) - BASIC_FIXUP_PATH(CURDIR) if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then # Add extra search paths on solaris for utilities like ar and as etc... @@ -487,13 +488,17 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], [ CONF_NAME=${with_conf_name} ]) # Test from where we are running configure, in or outside of src root. + AC_MSG_CHECKING([where to store configuration]) if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \ || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" \ || test "x$CURDIR" = "x$SRC_ROOT/make" ; then # We are running configure from the src root. # Create a default ./build/target-variant-debuglevel output root. if test "x${CONF_NAME}" = x; then + AC_MSG_RESULT([in default location]) CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + else + AC_MSG_RESULT([in build directory with custom name]) fi OUTPUT_ROOT="$SRC_ROOT/build/${CONF_NAME}" $MKDIR -p "$OUTPUT_ROOT" @@ -509,6 +514,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${SRC_ROOT}/build/!!"` fi OUTPUT_ROOT="$CURDIR" + AC_MSG_RESULT([in current directory]) # WARNING: This might be a bad thing to do. You need to be sure you want to # have a configuration in this directory. Do some sanity checks! diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index eea3039c51c..6eec8fa88cc 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ UNIQ="@UNIQ@" UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200" UNZIP="@UNZIP@" -SRC_ROOT="@SRC_ROOT@" +SRC_ROOT="@TOPDIR@" if [ "$OPENJDK_TARGET_OS" = "windows" ]; then PATH="@VS_PATH@" diff --git a/common/autoconf/configure b/common/autoconf/configure index 1376f48874a..d64b9354d4a 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -22,18 +22,25 @@ # questions. # -if test "x$BASH_VERSION" = x; then - echo This script needs bash to run. - echo It is recommended to use the configure script in the source tree root instead. +if test "x$1" != xCHECKME; then + echo "This script cannot be run directly." + echo "Use the 'configure' script in the top-level directory instead." exit 1 fi -conf_script_dir=`dirname $0` +# Now the next argument is the absolute top-level directory path. +# The TOPDIR variable is passed on to configure.ac. +TOPDIR="$2" +# Remove these two arguments to get to the user supplied arguments +shift +shift + +conf_script_dir="$TOPDIR/common/autoconf" if [ "$CUSTOM_CONFIG_DIR" = "" ]; then - conf_custom_script_dir="$conf_script_dir/../../closed/autoconf" + conf_custom_script_dir="$TOPDIR/closed/autoconf" else - conf_custom_script_dir=$CUSTOM_CONFIG_DIR + conf_custom_script_dir="$CUSTOM_CONFIG_DIR" fi ### @@ -226,10 +233,10 @@ conf_processed_arguments=("--enable-option-checking=fatal" "${conf_processed_arg ### if test -e $conf_custom_script_dir/generated-configure.sh; then # Custom source configure available; run that instead - echo Running custom generated-configure.sh + echo "Running custom generated-configure.sh" conf_script_to_run=$conf_custom_script_dir/generated-configure.sh else - echo Running generated-configure.sh + echo "Running generated-configure.sh" conf_script_to_run=$conf_script_dir/generated-configure.sh fi diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 2a7d125c2f1..29b678a8ede 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -33,7 +33,7 @@ AC_PREREQ([2.69]) AC_INIT(OpenJDK, jdk8, build-dev@openjdk.java.net,,http://openjdk.java.net) -AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_AUX_DIR([common/autoconf/build-aux]) m4_include([build-aux/pkg.m4]) # Include these first... diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 9e09ce14cda..b0852185ce2 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -1,3 +1,9 @@ +#!/bin/bash +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for OpenJDK jdk8. @@ -877,7 +883,7 @@ BUILD_LOG_PREVIOUS BUILD_LOG SYS_ROOT PATH_SEP -SRC_ROOT +TOPDIR ZERO_ARCHDEF DEFINE_CROSS_COMPILE_ARCH LP64 @@ -3156,7 +3162,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= -for ac_dir in build-aux "$srcdir"/build-aux; do +for ac_dir in common/autoconf/build-aux "$srcdir"/common/autoconf/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" @@ -3172,7 +3178,7 @@ for ac_dir in build-aux "$srcdir"/build-aux; do fi done if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in common/autoconf/build-aux \"$srcdir\"/common/autoconf/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -3274,7 +3280,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Include these first... # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4214,7 +4220,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1393240361 +DATE_WHEN_GENERATED=1393244882 ############################################################################### # @@ -13863,121 +13869,17 @@ $as_echo "$COMPILE_TYPE" >&6; } # Continue setting up basic stuff. Most remaining code require fundamental tools. - # Locate the directory of this script. - SCRIPT="$0" - AUTOCONF_DIR=`cd \`$DIRNAME $SCRIPT\`; $THEPWDCMD -L` - - # Where is the source? It is located two levels above the configure script. - CURDIR="$PWD" - cd "$AUTOCONF_DIR/../.." - SRC_ROOT="`$THEPWDCMD -L`" - - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - PATH_SEP=";" - - SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` - if test $SRC_ROOT_LENGTH -gt 100; then - as_fn_error $? "Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported" "$LINENO" 5 - fi - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin release" >&5 -$as_echo_n "checking cygwin release... " >&6; } - CYGWIN_VERSION=`$UNAME -r` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_VERSION" >&5 -$as_echo "$CYGWIN_VERSION" >&6; } - WINDOWS_ENV_VENDOR='cygwin' - WINDOWS_ENV_VERSION="$CYGWIN_VERSION" - - CYGWIN_VERSION_OK=`$ECHO $CYGWIN_VERSION | $GREP ^1.7.` - if test "x$CYGWIN_VERSION_OK" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&5 -$as_echo "$as_me: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&6;} - as_fn_error $? "Cannot continue" "$LINENO" 5 - fi - if test "x$CYGPATH" = x; then - as_fn_error $? "Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin root directory as unix-style path" >&5 -$as_echo_n "checking cygwin root directory as unix-style path... " >&6; } - # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away - cygwin_winpath_root=`cd / ; cmd /c cd | grep ".*"` - # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. - CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_ROOT_PATH" >&5 -$as_echo "$CYGWIN_ROOT_PATH" >&6; } - WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" - test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - as_fn_error $? "Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c." "$LINENO" 5 - fi - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys release" >&5 -$as_echo_n "checking msys release... " >&6; } - MSYS_VERSION=`$UNAME -r` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_VERSION" >&5 -$as_echo "$MSYS_VERSION" >&6; } - - WINDOWS_ENV_VENDOR='msys' - WINDOWS_ENV_VERSION="$MSYS_VERSION" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys root directory as unix-style path" >&5 -$as_echo_n "checking msys root directory as unix-style path... " >&6; } - # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away - MSYS_ROOT_PATH=`cd / ; cmd /c cd | grep ".*"` - - windows_path="$MSYS_ROOT_PATH" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - MSYS_ROOT_PATH="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - MSYS_ROOT_PATH="$unix_path" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_ROOT_PATH" >&5 -$as_echo "$MSYS_ROOT_PATH" >&6; } - WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" - else - as_fn_error $? "Unknown Windows environment. Neither cygwin nor msys was detected." "$LINENO" 5 - fi - - # Test if windows or unix (cygwin/msys) find is first in path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of 'find' is first on the PATH" >&5 -$as_echo_n "checking what kind of 'find' is first on the PATH... " >&6; } - FIND_BINARY_OUTPUT=`find --version 2>&1` - if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix style" >&5 -$as_echo "unix style" >&6; } - elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5 -$as_echo "Windows" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&5 -$as_echo "$as_me: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&5 -$as_echo "$as_me: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&6;} - as_fn_error $? "Cannot continue" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 -$as_echo "unknown" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: It seems that your find utility is non-standard." >&5 -$as_echo "$as_me: WARNING: It seems that your find utility is non-standard." >&2;} - fi - - else - PATH_SEP=":" - fi - - - - cd "$CURDIR" - + # We get the top-level directory from the supporting wrappers. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for top-level directory" >&5 +$as_echo_n "checking for top-level directory... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOPDIR" >&5 +$as_echo "$TOPDIR" >&6; } if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then # Input might be given as Windows format, start by converting to # unix format. - path="$SRC_ROOT" + path="$TOPDIR" new_path=`$CYGPATH -u "$path"` # Cygwin tries to hide some aspects of the Windows file system, such that binaries are @@ -13989,9 +13891,9 @@ $as_echo "$as_me: WARNING: It seems that your find utility is non-standard." >&2 # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of SRC_ROOT, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of SRC_ROOT, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of SRC_ROOT" "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of TOPDIR" "$LINENO" 5 fi # Call helper function which possibly converts this using DOS-style short mode. @@ -14029,14 +13931,14 @@ $as_echo "$as_me: The path of SRC_ROOT, which resolves as \"$path\", is invalid. if test "x$path" != "x$new_path"; then - SRC_ROOT="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting SRC_ROOT to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting SRC_ROOT to \"$new_path\"" >&6;} + TOPDIR="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} fi elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - path="$SRC_ROOT" + path="$TOPDIR" has_colon=`$ECHO $path | $GREP ^.:` new_path="$path" if test "x$has_colon" = x; then @@ -14067,9 +13969,9 @@ $as_echo "$as_me: Rewriting SRC_ROOT to \"$new_path\"" >&6;} fi if test "x$path" != "x$new_path"; then - SRC_ROOT="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting SRC_ROOT to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting SRC_ROOT to \"$new_path\"" >&6;} + TOPDIR="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} fi # Save the first 10 bytes of this path to the storage, so fixpath can work. @@ -14077,24 +13979,34 @@ $as_echo "$as_me: Rewriting SRC_ROOT to \"$new_path\"" >&6;} else # We're on a posix platform. Hooray! :) - path="$SRC_ROOT" + path="$TOPDIR" has_space=`$ECHO "$path" | $GREP " "` if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of SRC_ROOT, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of SRC_ROOT, which resolves as \"$path\", is invalid." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 fi # Use eval to expand a potential ~ eval path="$path" if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of SRC_ROOT, which resolves as \"$path\", is not found." "$LINENO" 5 + as_fn_error $? "The path of TOPDIR, which resolves as \"$path\", is not found." "$LINENO" 5 fi - SRC_ROOT="`cd "$path"; $THEPWDCMD -L`" + TOPDIR="`cd "$path"; $THEPWDCMD -L`" fi + + # SRC_ROOT is a traditional alias for TOPDIR. + SRC_ROOT=$TOPDIR + + # Locate the directory of this script. + AUTOCONF_DIR=$TOPDIR/common/autoconf + + # Save the current directory this script was started from + CURDIR="$PWD" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then # Input might be given as Windows format, start by converting to @@ -14217,6 +14129,103 @@ $as_echo "$as_me: The path of CURDIR, which resolves as \"$path\", is invalid." fi + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + PATH_SEP=";" + + SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` + if test $SRC_ROOT_LENGTH -gt 100; then + as_fn_error $? "Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported" "$LINENO" 5 + fi + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin release" >&5 +$as_echo_n "checking cygwin release... " >&6; } + CYGWIN_VERSION=`$UNAME -r` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_VERSION" >&5 +$as_echo "$CYGWIN_VERSION" >&6; } + WINDOWS_ENV_VENDOR='cygwin' + WINDOWS_ENV_VERSION="$CYGWIN_VERSION" + + CYGWIN_VERSION_OK=`$ECHO $CYGWIN_VERSION | $GREP ^1.7.` + if test "x$CYGWIN_VERSION_OK" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&5 +$as_echo "$as_me: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&6;} + as_fn_error $? "Cannot continue" "$LINENO" 5 + fi + if test "x$CYGPATH" = x; then + as_fn_error $? "Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin root directory as unix-style path" >&5 +$as_echo_n "checking cygwin root directory as unix-style path... " >&6; } + # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away + cygwin_winpath_root=`cd / ; cmd /c cd | grep ".*"` + # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. + CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_ROOT_PATH" >&5 +$as_echo "$CYGWIN_ROOT_PATH" >&6; } + WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" + test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + as_fn_error $? "Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c." "$LINENO" 5 + fi + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys release" >&5 +$as_echo_n "checking msys release... " >&6; } + MSYS_VERSION=`$UNAME -r` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_VERSION" >&5 +$as_echo "$MSYS_VERSION" >&6; } + + WINDOWS_ENV_VENDOR='msys' + WINDOWS_ENV_VERSION="$MSYS_VERSION" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys root directory as unix-style path" >&5 +$as_echo_n "checking msys root directory as unix-style path... " >&6; } + # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away + MSYS_ROOT_PATH=`cd / ; cmd /c cd | grep ".*"` + + windows_path="$MSYS_ROOT_PATH" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + MSYS_ROOT_PATH="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + MSYS_ROOT_PATH="$unix_path" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_ROOT_PATH" >&5 +$as_echo "$MSYS_ROOT_PATH" >&6; } + WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" + else + as_fn_error $? "Unknown Windows environment. Neither cygwin nor msys was detected." "$LINENO" 5 + fi + + # Test if windows or unix (cygwin/msys) find is first in path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of 'find' is first on the PATH" >&5 +$as_echo_n "checking what kind of 'find' is first on the PATH... " >&6; } + FIND_BINARY_OUTPUT=`find --version 2>&1` + if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix style" >&5 +$as_echo "unix style" >&6; } + elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5 +$as_echo "Windows" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&5 +$as_echo "$as_me: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&5 +$as_echo "$as_me: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&6;} + as_fn_error $? "Cannot continue" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 +$as_echo "unknown" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: It seems that your find utility is non-standard." >&5 +$as_echo "$as_me: WARNING: It seems that your find utility is non-standard." >&2;} + fi + + else + PATH_SEP=":" + fi + + if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then # Add extra search paths on solaris for utilities like ar and as etc... PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" @@ -14765,13 +14774,20 @@ fi # Test from where we are running configure, in or outside of src root. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to store configuration" >&5 +$as_echo_n "checking where to store configuration... " >&6; } if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \ || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" \ || test "x$CURDIR" = "x$SRC_ROOT/make" ; then # We are running configure from the src root. # Create a default ./build/target-variant-debuglevel output root. if test "x${CONF_NAME}" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default location" >&5 +$as_echo "in default location" >&6; } CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5 +$as_echo "in build directory with custom name" >&6; } fi OUTPUT_ROOT="$SRC_ROOT/build/${CONF_NAME}" $MKDIR -p "$OUTPUT_ROOT" @@ -14787,6 +14803,8 @@ fi CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${SRC_ROOT}/build/!!"` fi OUTPUT_ROOT="$CURDIR" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: in current directory" >&5 +$as_echo "in current directory" >&6; } # WARNING: This might be a bad thing to do. You need to be sure you want to # have a configuration in this directory. Do some sanity checks! diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index eef72634234..d09fb0ea1c4 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -70,8 +70,8 @@ ifeq (,$(findstring -R,$(MAKE))) endif # Specify where the common include directory for makefiles is. -ifeq (,$(findstring -I @SRC_ROOT@/make/common,$(MAKE))) - MAKE:=$(MAKE) -I @SRC_ROOT@/make/common +ifeq (,$(findstring -I @TOPDIR@/make/common,$(MAKE))) + MAKE:=$(MAKE) -I @TOPDIR@/make/common endif # The "human readable" name of this configuration @@ -136,10 +136,13 @@ endif SYS_ROOT:=@SYS_ROOT@ # Paths to the source code -SRC_ROOT:=@SRC_ROOT@ ADD_SRC_ROOT:=@ADD_SRC_ROOT@ OVERRIDE_SRC_ROOT:=@OVERRIDE_SRC_ROOT@ -TOPDIR:=@SRC_ROOT@ + +# The top-level directory of the forest (SRC_ROOT is a traditional alias) +TOPDIR:=@TOPDIR@ +SRC_ROOT:=@TOPDIR@ + OUTPUT_ROOT:=@OUTPUT_ROOT@ JDK_TOPDIR:=@JDK_TOPDIR@ LANGTOOLS_TOPDIR:=@LANGTOOLS_TOPDIR@ diff --git a/configure b/configure index dbb1da1367f..4ab8846d575 100644 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,5 +25,10 @@ # This is a thin wrapper which will call the real configure script, and # make sure that is called using bash. +# Get an absolute path to this script, since that determines the top-level directory. this_script_dir=`dirname $0` -bash $this_script_dir/common/autoconf/configure "$@" +this_script_dir=`cd $this_script_dir > /dev/null && pwd` + +# Delegate to wrapper, forcing wrapper to believe $0 is this script by using -c. +# This trick is needed to get autoconf to co-operate properly. +bash -c ". $this_script_dir/common/autoconf/configure" $this_script_dir/configure CHECKME $this_script_dir "$@" From bfbc3a0d513cd5b035f0bff2c2ea7bfeb80736bb Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Mon, 24 Feb 2014 21:54:22 -0800 Subject: [PATCH 187/265] 8025519: [TESTBUG] runtime/7107135/Test7107135.sh need to use COMPILEJAVA for javac task Modified some tests to use COMPILEJAVA instead of TESTJAVA for javac and include path Reviewed-by: dholmes, mseledtsov --- hotspot/test/TEST.groups | 3 --- hotspot/test/runtime/6929067/Test6929067.sh | 7 ++++--- hotspot/test/runtime/7107135/Test7107135.sh | 7 ++++--- hotspot/test/runtime/jsig/Test8017498.sh | 18 ++++++++---------- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index ae74a76a868..946cb2be8cf 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -67,10 +67,8 @@ needs_jdk = \ gc/metaspace/TestPerfCountersAndMemoryPools.java \ runtime/6819213/TestBootNativeLibraryPath.java \ runtime/6925573/SortMethodsTest.java \ - runtime/7107135/Test7107135.sh \ runtime/7158988/FieldMonitor.java \ runtime/7194254/Test7194254.java \ - runtime/jsig/Test8017498.sh \ runtime/Metaspace/FragmentMetaspace.java \ runtime/NMT/BaselineWithParameter.java \ runtime/NMT/JcmdScale.java \ @@ -175,7 +173,6 @@ needs_full_vm_compact1 = \ gc/startup_warnings/TestParallelScavengeSerialOld.java \ gc/startup_warnings/TestParNewCMS.java \ gc/startup_warnings/TestParNewSerialOld.java \ - runtime/6929067/Test6929067.sh \ runtime/SharedArchiveFile/SharedArchiveFile.java # Minimal VM on Compact 2 adds in some compact2 tests diff --git a/hotspot/test/runtime/6929067/Test6929067.sh b/hotspot/test/runtime/6929067/Test6929067.sh index 4fa7fe2b51d..3757278ba3f 100644 --- a/hotspot/test/runtime/6929067/Test6929067.sh +++ b/hotspot/test/runtime/6929067/Test6929067.sh @@ -4,6 +4,7 @@ ## @test Test6929067.sh ## @bug 6929067 ## @bug 8021296 +## @bug 8025519 ## @summary Stack guard pages should be removed when thread is detached ## @run shell Test6929067.sh ## @@ -113,7 +114,7 @@ LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE}:/usr/lib:$LD_LIBRARY_ export LD_LIBRARY_PATH cp ${TESTSRC}${FS}*.java ${THIS_DIR} -${TESTJAVA}${FS}bin${FS}javac *.java +${COMPILEJAVA}${FS}bin${FS}javac *.java echo "Architecture: ${ARCH}" echo "Compilation flag: ${COMP_FLAG}" @@ -123,8 +124,8 @@ echo "VM type: ${VMTYPE}" # for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. $gcc_cmd -DLINUX ${COMP_FLAG} -o invoke \ - -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \ - -L${TESTJAVA}/jre/lib/${ARCH}/${VMTYPE} \ + -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \ + -L${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE} \ ${TESTSRC}${FS}invoke.c -ljvm -lpthread ./invoke diff --git a/hotspot/test/runtime/7107135/Test7107135.sh b/hotspot/test/runtime/7107135/Test7107135.sh index f261aec3fc7..0aa0e864e1e 100644 --- a/hotspot/test/runtime/7107135/Test7107135.sh +++ b/hotspot/test/runtime/7107135/Test7107135.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011 SAP AG. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -29,6 +29,7 @@ ## @test Test7107135.sh ## @bug 7107135 ## @bug 8021296 +## @bug 8025519 ## @summary Stack guard pages lost after loading library with executable stack. ## @run shell Test7107135.sh ## @@ -64,10 +65,10 @@ ARCH=`uname -m` THIS_DIR=. cp ${TESTSRC}${FS}*.java ${THIS_DIR} -${TESTJAVA}${FS}bin${FS}javac *.java +${COMPILEJAVA}${FS}bin${FS}javac *.java $gcc_cmd -fPIC -shared -c -o test.o \ - -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux \ + -I${COMPILEJAVA}${FS}include -I${COMPILEJAVA}${FS}include${FS}linux \ ${TESTSRC}${FS}test.c ld -shared -z execstack -o libtest-rwx.so test.o diff --git a/hotspot/test/runtime/jsig/Test8017498.sh b/hotspot/test/runtime/jsig/Test8017498.sh index 0c3c2dbcfe1..a28bbe4b478 100644 --- a/hotspot/test/runtime/jsig/Test8017498.sh +++ b/hotspot/test/runtime/jsig/Test8017498.sh @@ -30,8 +30,9 @@ ## @bug 8020791 ## @bug 8021296 ## @bug 8022301 +## @bug 8025519 ## @summary sigaction(sig) results in process hang/timed-out if sig is much greater than SIGRTMAX -## @run shell/timeout=30 Test8017498.sh +## @run shell/timeout=60 Test8017498.sh ## if [ "${TESTSRC}" = "" ] @@ -55,12 +56,9 @@ case "$OS" in echo "WARNING: gcc not found. Cannot execute test." 2>&1 exit 0; fi - if [ "$VM_BITS" = "64" ] - then - MY_LD_PRELOAD=${TESTJAVA}${FS}jre${FS}lib${FS}amd64${FS}libjsig.so - else - MY_LD_PRELOAD=${TESTJAVA}${FS}jre${FS}lib${FS}i386${FS}libjsig.so - EXTRA_CFLAG=-m32 + MY_LD_PRELOAD=${TESTJAVA}${FS}jre${FS}lib${FS}${VM_CPU}${FS}libjsig.so + if [ "$VM_BITS" == "32" ] && [ "$VM_CPU" != "arm" ] && [ "$VM_CPU" != "ppc" ]; then + EXTRA_CFLAG=-m32 fi echo MY_LD_PRELOAD = ${MY_LD_PRELOAD} ;; @@ -73,13 +71,13 @@ esac THIS_DIR=. cp ${TESTSRC}${FS}*.java ${THIS_DIR} -${TESTJAVA}${FS}bin${FS}javac *.java +${COMPILEJAVA}${FS}bin${FS}javac *.java $gcc_cmd -DLINUX -fPIC -shared \ ${EXTRA_CFLAG} -z noexecstack \ -o ${TESTSRC}${FS}libTestJNI.so \ - -I${TESTJAVA}${FS}include \ - -I${TESTJAVA}${FS}include${FS}linux \ + -I${COMPILEJAVA}${FS}include \ + -I${COMPILEJAVA}${FS}include${FS}linux \ ${TESTSRC}${FS}TestJNI.c # run the java test in the background From e3931e81eb29872ff7ea664464ffa419e60dd465 Mon Sep 17 00:00:00 2001 From: Niclas Adlertz Date: Tue, 25 Feb 2014 10:26:21 +0100 Subject: [PATCH 188/265] 8032894: Remove dead code in Pressure::lower Remove dead code in Pressure::lower Reviewed-by: kvn, roland --- hotspot/src/share/vm/opto/chaitin.hpp | 46 ++++++++++++++++++++++++--- hotspot/src/share/vm/opto/ifg.cpp | 42 ++++++++++-------------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index fb114bbd930..545e5882bc4 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -501,8 +501,9 @@ private: // Used for aggressive coalescing. void build_ifg_virtual( ); + // used when computing the register pressure for each block in the CFG. This + // is done during IFG creation. class Pressure { - public: // keeps track of the register pressure at the current // instruction (used when stepping backwards in the block) uint _current_pressure; @@ -518,6 +519,7 @@ private: // number of live ranges that constitute high register pressure const uint _high_pressure_limit; + public: // lower the register pressure and look for a low to high pressure // transition @@ -525,9 +527,6 @@ private: _current_pressure -= lrg.reg_pressure(); if (_current_pressure == _high_pressure_limit) { _high_pressure_index = location; - if (_current_pressure > _final_pressure) { - _final_pressure = _current_pressure + 1; - } } } @@ -540,6 +539,45 @@ private: } } + uint high_pressure_index() const { + return _high_pressure_index; + } + + uint final_pressure() const { + return _final_pressure; + } + + uint current_pressure() const { + return _current_pressure; + } + + uint high_pressure_limit() const { + return _high_pressure_limit; + } + + void lower_high_pressure_index() { + _high_pressure_index--; + } + + void set_high_pressure_index_to_block_start() { + _high_pressure_index = 0; + } + + void check_pressure_at_fatproj(uint fatproj_location, RegMask& fatproj_mask) { + // this pressure is only valid at this instruction, i.e. we don't need to lower + // the register pressure since the fat proj was never live before (going backwards) + uint new_pressure = current_pressure() + fatproj_mask.Size(); + if (new_pressure > final_pressure()) { + _final_pressure = new_pressure; + } + + // if we were at a low pressure and now and the fat proj is at high pressure, record the fat proj location + // as coming from a low to high (to low again) + if (current_pressure() <= high_pressure_limit() && new_pressure > high_pressure_limit()) { + _high_pressure_index = fatproj_location; + } + } + Pressure(uint high_pressure_index, uint high_pressure_limit) : _current_pressure(0) , _high_pressure_index(high_pressure_index) diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 24aab15143f..4b102d68589 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -439,8 +439,8 @@ void PhaseChaitin::lower_pressure(Block* b, uint location, LRG& lrg, IndexSet* l } } } - assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); - assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); + assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } /* Go to the first non-phi index in a block */ @@ -513,8 +513,8 @@ void PhaseChaitin::compute_initial_block_pressure(Block* b, IndexSet* liveout, P raise_pressure(b, lrg, int_pressure, float_pressure); lid = elements.next(); } - assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); - assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); + assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } /* @@ -548,17 +548,7 @@ bool PhaseChaitin::remove_node_if_not_used(Block* b, uint location, Node* n, uin void PhaseChaitin::check_for_high_pressure_transition_at_fatproj(uint& block_reg_pressure, uint location, LRG& lrg, Pressure& pressure, const int op_regtype) { RegMask mask_tmp = lrg.mask(); mask_tmp.AND(*Matcher::idealreg2regmask[op_regtype]); - // this pressure is only valid at this instruction, i.e. we don't need to lower - // the register pressure since the fat proj was never live before (going backwards) - uint new_pressure = pressure._current_pressure + mask_tmp.Size(); - if (new_pressure > pressure._final_pressure) { - pressure._final_pressure = new_pressure; - } - // if we were at a low pressure and now at the fat proj is at high pressure, record the fat proj location - // as coming from a low to high (to low again) - if (pressure._current_pressure <= pressure._high_pressure_limit && new_pressure > pressure._high_pressure_limit) { - pressure._high_pressure_index = location; - } + pressure.check_pressure_at_fatproj(location, mask_tmp); } /* @@ -700,8 +690,8 @@ void PhaseChaitin::add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, do // Newly live things assumed live from here to top of block lrg._area += cost; raise_pressure(b, lrg, int_pressure, float_pressure); - assert(int_pressure._current_pressure == count_int_pressure(liveout), "the int pressure is incorrect"); - assert(float_pressure._current_pressure == count_float_pressure(liveout), "the float pressure is incorrect"); + assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); + assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } assert(!(lrg._area < 0.0), "negative spill area" ); } @@ -710,13 +700,13 @@ void PhaseChaitin::add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, do /* * If we run off the top of the block with high pressure just record that the * whole block is high pressure. (Even though we might have a transition - * lower down in the block) + * later down in the block) */ void PhaseChaitin::check_for_high_pressure_block(Pressure& pressure) { // current pressure now means the pressure before the first instruction in the block // (since we have stepped through all instructions backwards) - if (pressure._current_pressure > pressure._high_pressure_limit) { - pressure._high_pressure_index = 0; + if (pressure.current_pressure() > pressure.high_pressure_limit()) { + pressure.set_high_pressure_index_to_block_start(); } } @@ -725,7 +715,7 @@ void PhaseChaitin::check_for_high_pressure_block(Pressure& pressure) { * and set the high pressure index for the block */ void PhaseChaitin::adjust_high_pressure_index(Block* b, uint& block_hrp_index, Pressure& pressure) { - uint i = pressure._high_pressure_index; + uint i = pressure.high_pressure_index(); if (i < b->number_of_nodes() && i < b->end_idx() + 1) { Node* cur = b->get_node(i); while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { @@ -789,8 +779,8 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { if (!liveout.member(lid) && n->Opcode() != Op_SafePoint) { if (remove_node_if_not_used(block, location, n, lid, &liveout)) { - float_pressure._high_pressure_index--; - int_pressure._high_pressure_index--; + float_pressure.lower_high_pressure_index(); + int_pressure.lower_high_pressure_index(); continue; } if (lrg._fat_proj) { @@ -837,13 +827,13 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { adjust_high_pressure_index(block, block->_ihrp_index, int_pressure); adjust_high_pressure_index(block, block->_fhrp_index, float_pressure); // set the final_pressure as the register pressure for the block - block->_reg_pressure = int_pressure._final_pressure; - block->_freg_pressure = float_pressure._final_pressure; + block->_reg_pressure = int_pressure.final_pressure(); + block->_freg_pressure = float_pressure.final_pressure(); #ifndef PRODUCT // Gather Register Pressure Statistics if (PrintOptoStatistics) { - if (block->_reg_pressure > int_pressure._high_pressure_limit || block->_freg_pressure > float_pressure._high_pressure_limit) { + if (block->_reg_pressure > int_pressure.high_pressure_limit() || block->_freg_pressure > float_pressure.high_pressure_limit()) { _high_pressure++; } else { _low_pressure++; From a609fe84bb9afc68df4c6e71c77078d1fe8c4f9a Mon Sep 17 00:00:00 2001 From: Albert Noll Date: Tue, 25 Feb 2014 13:52:37 +0100 Subject: [PATCH 189/265] 8034775: Failing to initialize VM when running with negative value for -XX:CICompilerCount Ensure appropriate min. number of compiler threads (1 for non-tiered, and 2 for tiered) Reviewed-by: kvn --- hotspot/src/share/vm/runtime/arguments.cpp | 4 ++ .../startup/NumCompilerThreadsCheck.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 hotspot/test/compiler/startup/NumCompilerThreadsCheck.java diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5a6de983469..b908439bcd9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2388,6 +2388,10 @@ bool Arguments::check_vm_args_consistency() { status &= verify_interval(NmethodSweepFraction, 1, ReservedCodeCacheSize/K, "NmethodSweepFraction"); status &= verify_interval(NmethodSweepActivity, 0, 2000, "NmethodSweepActivity"); + // TieredCompilation needs at least 2 compiler threads. + const int num_min_compiler_threads = (TieredCompilation) ? 2 : 1; + status &=verify_min_value(CICompilerCount, num_min_compiler_threads, "CICompilerCount"); + return status; } diff --git a/hotspot/test/compiler/startup/NumCompilerThreadsCheck.java b/hotspot/test/compiler/startup/NumCompilerThreadsCheck.java new file mode 100644 index 00000000000..e7e92d379ac --- /dev/null +++ b/hotspot/test/compiler/startup/NumCompilerThreadsCheck.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034775 + * @summary Ensures correct minimal number of compiler threads (provided by -XX:CICompilerCount=) + * @library /testlibrary + */ +import com.oracle.java.testlibrary.*; + +public class NumCompilerThreadsCheck { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:CICompilerCount=-1"); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + + String expectedOutput = "CICompilerCount of -1 is invalid"; + out.shouldContain(expectedOutput); + } +} From 532b570e81065ddb1df6f61eb1e0bec82b37472f Mon Sep 17 00:00:00 2001 From: Niclas Adlertz Date: Tue, 25 Feb 2014 14:09:02 +0100 Subject: [PATCH 190/265] 8032656: Tag the MachSpillCopies with purpose information Subclassed the MachSpillCopyNode with different subnodes for different spill purposes to enhance debugging / visualization Reviewed-by: kvn, roland --- hotspot/src/share/vm/opto/chaitin.cpp | 2 +- hotspot/src/share/vm/opto/chaitin.hpp | 9 ++-- hotspot/src/share/vm/opto/coalesce.cpp | 6 +-- hotspot/src/share/vm/opto/machnode.hpp | 61 +++++++++++++++++++++++-- hotspot/src/share/vm/opto/reg_split.cpp | 36 +++++++-------- 5 files changed, 84 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index d79b62694f1..0f64bccd6ba 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -1799,7 +1799,7 @@ bool PhaseChaitin::stretch_base_pointer_live_ranges(ResourceArea *a) { Block *phi_block = _cfg.get_block_for_node(phi); if (_cfg.get_block_for_node(phi_block->pred(2)) == block) { const RegMask *mask = C->matcher()->idealreg2spillmask[Op_RegI]; - Node *spill = new (C) MachSpillCopyNode( phi, *mask, *mask ); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::LoopPhiInput, phi, *mask, *mask); insert_proj( phi_block, 1, spill, maxlrg++ ); n->set_req(1,spill); must_recompute_live = true; diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index 545e5882bc4..f11b5b1f416 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -34,10 +34,9 @@ #include "opto/phase.hpp" #include "opto/regalloc.hpp" #include "opto/regmask.hpp" +#include "opto/machnode.hpp" class LoopTree; -class MachCallNode; -class MachSafePointNode; class Matcher; class PhaseCFG; class PhaseLive; @@ -424,8 +423,8 @@ class PhaseChaitin : public PhaseRegAlloc { uint _simplified; // Linked list head of simplified LRGs // Helper functions for Split() - uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray splits, int slidx ); - uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ); + uint split_DEF(Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray splits, int slidx ); + uint split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ); //------------------------------clone_projs------------------------------------ // After cloning some rematerialized instruction, clone any MachProj's that @@ -447,7 +446,7 @@ class PhaseChaitin : public PhaseRegAlloc { int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru); // True if lidx is used before any real register is def'd in the block bool prompt_use( Block *b, uint lidx ); - Node *get_spillcopy_wide( Node *def, Node *use, uint uidx ); + Node *get_spillcopy_wide(MachSpillCopyNode::SpillType spill_type, Node *def, Node *use, uint uidx ); // Insert the spill at chosen location. Skip over any intervening Proj's or // Phis. Skip over a CatchNode and projs, inserting in the fall-through block // instead. Update high-pressure indices. Create a new live range. diff --git a/hotspot/src/share/vm/opto/coalesce.cpp b/hotspot/src/share/vm/opto/coalesce.cpp index bd207b584a1..5579d90c485 100644 --- a/hotspot/src/share/vm/opto/coalesce.cpp +++ b/hotspot/src/share/vm/opto/coalesce.cpp @@ -291,7 +291,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { _phc.clone_projs(pred, pred->end_idx(), m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; - copy = new (C) MachSpillCopyNode(m, *rm, *rm); + copy = new (C) MachSpillCopyNode(MachSpillCopyNode::PhiInput, m, *rm, *rm); // Find a good place to insert. Kinda tricky, use a subroutine insert_copy_with_overlap(pred,copy,phi_name,src_name); } @@ -325,7 +325,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; - copy = new (C) MachSpillCopyNode(m, *rm, *rm); + copy = new (C) MachSpillCopyNode(MachSpillCopyNode::TwoAddress, m, *rm, *rm); // Insert the copy in the basic block, just before us b->insert_node(copy, l++); } @@ -372,7 +372,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { continue; // Live out; do not pre-split // Split the lrg at this use const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()]; - Node *copy = new (C) MachSpillCopyNode( inp, *rm, *rm ); + Node* copy = new (C) MachSpillCopyNode(MachSpillCopyNode::DebugUse, inp, *rm, *rm); // Insert the copy in the use-def chain n->set_req(inpidx, copy ); // Insert the copy in the basic block, just before us diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 5ea42a43fce..55d7e515882 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -520,12 +520,33 @@ public: // Machine SpillCopy Node. Copies 1 or 2 words from any location to any // location (stack or register). class MachSpillCopyNode : public MachIdealNode { +public: + enum SpillType { + TwoAddress, // Inserted when coalescing of a two-address-instruction node and its input fails + PhiInput, // Inserted when coalescing of a phi node and its input fails + DebugUse, // Inserted as debug info spills to safepoints in non-frequent blocks + LoopPhiInput, // Pre-split compares of loop-phis + Definition, // An lrg marked as spilled will be spilled to memory right after its definition, + // if in high pressure region or the lrg is bound + RegToReg, // A register to register move + RegToMem, // A register to memory move + MemToReg, // A memory to register move + PhiLocationDifferToInputLocation, // When coalescing phi nodes in PhaseChaitin::Split(), a move spill is inserted if + // the phi and its input resides at different locations (i.e. reg or mem) + BasePointerToMem, // Spill base pointer to memory at safepoint + InputToRematerialization, // When rematerializing a node we stretch the inputs live ranges, and they might be + // stretched beyond a new definition point, therefore we split out new copies instead + CallUse, // Spill use at a call + Bound // An lrg marked as spill that is bound and needs to be spilled at a use + }; +private: const RegMask *_in; // RegMask for input const RegMask *_out; // RegMask for output const Type *_type; + const SpillType _spill_type; public: - MachSpillCopyNode( Node *n, const RegMask &in, const RegMask &out ) : - MachIdealNode(), _in(&in), _out(&out), _type(n->bottom_type()) { + MachSpillCopyNode(SpillType spill_type, Node *n, const RegMask &in, const RegMask &out ) : + MachIdealNode(), _spill_type(spill_type), _in(&in), _out(&out), _type(n->bottom_type()) { init_class_id(Class_MachSpillCopy); init_flags(Flag_is_Copy); add_req(NULL); @@ -544,8 +565,42 @@ public: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; virtual uint size(PhaseRegAlloc *ra_) const; + #ifndef PRODUCT - virtual const char *Name() const { return "MachSpillCopy"; } + virtual const char *Name() const { + switch (_spill_type) { + case TwoAddress: + return "TwoAddressSpillCopy"; + case PhiInput: + return "PhiInputSpillCopy"; + case DebugUse: + return "DebugUseSpillCopy"; + case LoopPhiInput: + return "LoopPhiInputSpillCopy"; + case Definition: + return "DefinitionSpillCopy"; + case RegToReg: + return "RegToRegSpillCopy"; + case RegToMem: + return "RegToMemSpillCopy"; + case MemToReg: + return "MemToRegSpillCopy"; + case PhiLocationDifferToInputLocation: + return "PhiLocationDifferToInputLocationSpillCopy"; + case BasePointerToMem: + return "BasePointerToMemSpillCopy"; + case InputToRematerialization: + return "InputToRematerializationSpillCopy"; + case CallUse: + return "CallUseSpillCopy"; + case Bound: + return "BoundSpillCopy"; + default: + assert(false, "Must have valid spill type"); + return "MachSpillCopy"; + } + } + virtual void format( PhaseRegAlloc *, outputStream *st ) const; #endif }; diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index cfcecadd338..7ec346bc6a9 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -55,7 +55,7 @@ static const char out_of_nodes[] = "out of nodes during split"; // Get a SpillCopy node with wide-enough masks. Use the 'wide-mask', the // wide ideal-register spill-mask if possible. If the 'wide-mask' does // not cover the input (or output), use the input (or output) mask instead. -Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { +Node *PhaseChaitin::get_spillcopy_wide(MachSpillCopyNode::SpillType spill_type, Node *def, Node *use, uint uidx ) { // If ideal reg doesn't exist we've got a bad schedule happening // that is forcing us to spill something that isn't spillable. // Bail rather than abort @@ -93,7 +93,7 @@ Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { // Here we assume a trip through memory is required. w_i_mask = &C->FIRST_STACK_mask(); } - return new (C) MachSpillCopyNode( def, *w_i_mask, *w_o_mask ); + return new (C) MachSpillCopyNode(spill_type, def, *w_i_mask, *w_o_mask ); } //------------------------------insert_proj------------------------------------ @@ -159,7 +159,7 @@ uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node ** assert( loc >= 0, "must insert past block head" ); // Get a def-side SpillCopy - Node *spill = get_spillcopy_wide(def,NULL,0); + Node *spill = get_spillcopy_wide(MachSpillCopyNode::Definition, def, NULL, 0); // Did we fail to split?, then bail if (!spill) { return 0; @@ -180,7 +180,7 @@ uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node ** //------------------------------split_USE-------------------------------------- // Splits at uses can involve redeffing the LRG, so no CISC Spilling there. // Debug uses want to know if def is already stack enabled. -uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint maxlrg, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ) { +uint PhaseChaitin::split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Block *b, Node *use, uint useidx, uint maxlrg, bool def_down, bool cisc_sp, GrowableArray splits, int slidx ) { #ifdef ASSERT // Increment the counter for this lrg splits.at_put(slidx, splits.at(slidx)+1); @@ -216,7 +216,7 @@ uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint // DEF is UP, so must copy it DOWN and hook in USE // Insert SpillCopy before the USE, which uses DEF as its input, // and defs a new live range, which is used by this node. - Node *spill = get_spillcopy_wide(def,use,useidx); + Node *spill = get_spillcopy_wide(spill_type, def,use,useidx); // did we fail to split? if (!spill) { // Bail @@ -268,7 +268,7 @@ uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint bindex = b->find_node(use); } - Node *spill = get_spillcopy_wide( def, use, useidx ); + Node *spill = get_spillcopy_wide(spill_type, def, use, useidx ); if( !spill ) return 0; // Bailed out // Insert SpillCopy before the USE, which uses the reaching DEF as // its input, and defs a new live range, which is used by this node. @@ -327,7 +327,7 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint Block *b_def = _cfg.get_block_for_node(def); int idx_def = b_def->find_node(def); - Node *in_spill = get_spillcopy_wide( in, def, i ); + Node *in_spill = get_spillcopy_wide(MachSpillCopyNode::InputToRematerialization, in, def, i ); if( !in_spill ) return 0; // Bailed out insert_proj(b_def,idx_def,in_spill,maxlrg++); if( b_def == b ) @@ -935,7 +935,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // This def has been rematerialized a couple of times without // progress. It doesn't care if it lives UP or DOWN, so // spill it down now. - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false,splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::BasePointerToMem, def,b,n,inpidx,maxlrg,false,false,splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1015,7 +1015,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { !is_vect && umask.is_misaligned_pair())) { // These need a Split regardless of overlap or pressure // SPLIT - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,dup,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::Bound, def,b,n,inpidx,maxlrg,dup,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1027,7 +1027,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if (UseFPUForSpilling && n->is_MachCall() && !uup && !dup ) { // The use at the call can force the def down so insert // a split before the use to allow the def more freedom. - maxlrg = split_USE(def,b,n,inpidx,maxlrg,dup,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::CallUse, def,b,n,inpidx,maxlrg,dup,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1063,7 +1063,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { else { // Both are either up or down, and there is no overlap if( dup ) { // If UP, reg->reg copy // COPY ACROSS HERE - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToReg, def,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1075,10 +1075,10 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // First Split-UP to move value into Register uint def_ideal = def->ideal_reg(); const RegMask* tmp_rm = Matcher::idealreg2regmask[def_ideal]; - Node *spill = new (C) MachSpillCopyNode(def, dmask, *tmp_rm); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::MemToReg, def, dmask, *tmp_rm); insert_proj( b, insidx, spill, maxlrg ); // Then Split-DOWN as if previous Split was DEF - maxlrg = split_USE(spill,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToMem, spill,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1103,7 +1103,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { } } // COPY DOWN HERE - NO DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,false,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::RegToMem, def,b,n,inpidx,maxlrg,false,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1118,7 +1118,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { else { // DOWN, Split-UP and check register pressure if( is_high_pressure( b, &lrgs(useidx), insidx ) ) { // COPY UP HERE - NO DEF - CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,true,true, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::MemToReg, def,b,n,inpidx,maxlrg,true,true, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1126,7 +1126,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { insidx++; // Reset iterator to skip USE side split } else { // LRP // COPY UP HERE - WITH DEF - NO CISC SPILL - maxlrg = split_USE(def,b,n,inpidx,maxlrg,true,false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::MemToReg, def,b,n,inpidx,maxlrg,true,false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; @@ -1229,7 +1229,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if (C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) { // Check when generating nodes return 0; } - Node *spill = new (C) MachSpillCopyNode(use,use_rm,def_rm); + Node *spill = new (C) MachSpillCopyNode(MachSpillCopyNode::MemToReg, use,use_rm,def_rm); n->set_req(copyidx,spill); n->as_MachSpillCopy()->set_in_RegMask(def_rm); // Put the spill just before the copy @@ -1336,7 +1336,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // Grab the UP/DOWN sense for the input u1 = UP[pidx][slidx]; if( u1 != (phi_up != 0)) { - maxlrg = split_USE(def, b, phi, i, maxlrg, !u1, false, splits,slidx); + maxlrg = split_USE(MachSpillCopyNode::PhiLocationDifferToInputLocation, def, b, phi, i, maxlrg, !u1, false, splits,slidx); // If it wasn't split bail if (!maxlrg) { return 0; From 18489cc7a410aff493f42bc6eae0236255574274 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 25 Feb 2014 18:56:10 +0530 Subject: [PATCH 191/265] 8030197: Nashorn: Object.defineProperty() can be lured to change fixed NaN property Reviewed-by: attila, jlaskey --- .../objects/AccessorPropertyDescriptor.java | 12 +++++ .../objects/DataPropertyDescriptor.java | 13 ++++++ .../objects/GenericPropertyDescriptor.java | 17 +++++++ .../internal/runtime/PropertyDescriptor.java | 7 +++ .../internal/runtime/ScriptObject.java | 2 +- nashorn/test/script/basic/JDK-8030197.js | 46 +++++++++++++++++++ 6 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/basic/JDK-8030197.js diff --git a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java index b37316207bf..4d3fd43d32e 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java @@ -184,6 +184,18 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr return ACCESSOR; } + @Override + public boolean hasAndEquals(final PropertyDescriptor otherDesc) { + if (! (otherDesc instanceof AccessorPropertyDescriptor)) { + return false; + } + final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)otherDesc; + return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) && + (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) && + (!has(GET) || sameValue(get, other.get)) && + (!has(SET) || sameValue(set, other.set)); + } + @Override public boolean equals(final Object obj) { if (this == obj) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java index ef3f0a30679..39325627b2d 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java @@ -171,6 +171,19 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper return DATA; } + @Override + public boolean hasAndEquals(final PropertyDescriptor otherDesc) { + if (! (otherDesc instanceof DataPropertyDescriptor)) { + return false; + } + + final DataPropertyDescriptor other = (DataPropertyDescriptor)otherDesc; + return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) && + (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) && + (!has(WRITABLE) || sameValue(writable, other.writable)) && + (!has(VALUE) || sameValue(value, other.value)); + } + @Override public boolean equals(final Object obj) { if (this == obj) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java index f5662efa324..221fe002bcd 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java @@ -148,6 +148,23 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro return GENERIC; } + @Override + public boolean hasAndEquals(final PropertyDescriptor other) { + if (has(CONFIGURABLE) && other.has(CONFIGURABLE)) { + if (isConfigurable() != other.isConfigurable()) { + return false; + } + } + + if (has(ENUMERABLE) && other.has(ENUMERABLE)) { + if (isEnumerable() != other.isEnumerable()) { + return false; + } + } + + return true; + } + @Override public boolean equals(final Object obj) { if (this == obj) { diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java index 49a7a9d6bc4..f36bd45e197 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java @@ -151,5 +151,12 @@ public interface PropertyDescriptor { * @return true if property exists in implementor */ public boolean has(Object key); + + /** + * Check existence and compare attributes of descriptors. + * + * @return true if every field of this desc exists in otherDesc and has the same value. + */ + public boolean hasAndEquals(PropertyDescriptor otherDesc); } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java index 4b85ed4ed5c..4b3bb939411 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -469,7 +469,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return true; } - if (currentDesc.equals(newDesc)) { + if (newDesc.hasAndEquals(currentDesc)) { // every descriptor field of the new is same as the current return true; } diff --git a/nashorn/test/script/basic/JDK-8030197.js b/nashorn/test/script/basic/JDK-8030197.js new file mode 100644 index 00000000000..366d33df3ad --- /dev/null +++ b/nashorn/test/script/basic/JDK-8030197.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/** + * JDK-8030197: Nashorn: Object.defineProperty() can be lured to change fixed NaN property + * + * @test + * @run + */ + +function str(n) { + var a = new Uint8Array(new Float64Array([n]).buffer); + return Array.apply(null, a).reduceRight( + function(acc, v){ + return acc + (v < 10 ? "0" : "") + v.toString(16); + }, ""); +} + +var o = Object.defineProperty({}, "NaN", { value: NaN }) +var str1 = str(o.NaN); +Object.defineProperty(o, "NaN", { value: 0/0 }) +var str2 = str(o.NaN); +if (str1 != str2) { + fail("NaN bit pattern changed"); +} From e7066f39237bbe038a9286f007671e33274a0d68 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 25 Feb 2014 15:19:32 +0100 Subject: [PATCH 192/265] 8035725: Must keep microsoft VS_PATH on PATH after toolchain detection Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 27 ++++++++++++++------------ common/autoconf/toolchain.m4 | 15 ++++++++------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index b0852185ce2..227c7fbbb07 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4220,7 +4220,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1393244882 +DATE_WHEN_GENERATED=1393327380 ############################################################################### # @@ -26393,18 +26393,10 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ORG_CXXFLAGS="$CXXFLAGS" ORG_OBJCFLAGS="$OBJCFLAGS" - # autoconf magic only relies on PATH, so update it if tools dir is specified - OLD_PATH="$PATH" - - # For solaris we really need solaris tools, and not the GNU equivalent. - # The build tools on Solaris reside in /usr/ccs (C Compilation System), - # so add that to path before starting to probe. - # FIXME: This was originally only done for AS,NM,GNM,STRIP,MCS,OBJCOPY,OBJDUMP. - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - PATH="/usr/ccs/bin:$PATH" - fi - # On Windows, we need to detect the visual studio installation first. + # This will change the PATH, but we need to keep that new PATH even + # after toolchain detection is done, since the compiler (on x86) uses + # it for DLL resolution in runtime. if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then # Store path to cygwin link.exe to help excluding it when searching for @@ -27215,6 +27207,17 @@ $as_echo "$as_me: or run \"bash.exe -l\" from a VS command prompt and then run c fi + # autoconf magic only relies on PATH, so update it if tools dir is specified + OLD_PATH="$PATH" + + # For solaris we really need solaris tools, and not the GNU equivalent. + # The build tools on Solaris reside in /usr/ccs (C Compilation System), + # so add that to path before starting to probe. + # FIXME: This was originally only done for AS,NM,GNM,STRIP,MCS,OBJCOPY,OBJDUMP. + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + PATH="/usr/ccs/bin:$PATH" + fi + # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to # override all other locations. if test "x$TOOLS_DIR" != x; then diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index b7e043fdf6d..7110d783205 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -164,6 +164,14 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION], ORG_CXXFLAGS="$CXXFLAGS" ORG_OBJCFLAGS="$OBJCFLAGS" + # On Windows, we need to detect the visual studio installation first. + # This will change the PATH, but we need to keep that new PATH even + # after toolchain detection is done, since the compiler (on x86) uses + # it for DLL resolution in runtime. + if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then + TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV + fi + # autoconf magic only relies on PATH, so update it if tools dir is specified OLD_PATH="$PATH" @@ -175,11 +183,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_PRE_DETECTION], PATH="/usr/ccs/bin:$PATH" fi - # On Windows, we need to detect the visual studio installation first. - if test "x$OPENJDK_BUILD_OS" = "xwindows" && test "x$TOOLCHAIN_TYPE" = "xmicrosoft"; then - TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV - fi - # Finally add TOOLS_DIR at the beginning, to allow --with-tools-dir to # override all other locations. if test "x$TOOLS_DIR" != x; then @@ -663,7 +666,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS], # Check for extra potential brokenness. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # On Windows, double-check that we got the right compiler. - CC_VERSION_OUTPUT=`$CC 2>&1 | $HEAD -n 1 | $TR -d '\r'` + CC_VERSION_OUTPUT=`$CC 2>&1 | $HEAD -n 1 | $TR -d '\r'` COMPILER_CPU_TEST=`$ECHO $CC_VERSION_OUTPUT | $SED -n "s/^.* \(.*\)$/\1/p"` if test "x$OPENJDK_TARGET_CPU" = "xx86"; then if test "x$COMPILER_CPU_TEST" != "x80x86"; then From 5d4b624caf1890475feea060b683d53d525b9e4f Mon Sep 17 00:00:00 2001 From: Niclas Adlertz Date: Tue, 25 Feb 2014 17:51:27 +0100 Subject: [PATCH 193/265] 8033260: assert(lrg._area >= 0.0) failed: negative spill area Change type from float to double on block frequency, and add check for +Inf - +Inf operation Reviewed-by: kvn, roland --- .../classes/sun/jvm/hotspot/opto/Block.java | 8 ++--- hotspot/src/share/vm/opto/block.hpp | 30 +++++++++---------- hotspot/src/share/vm/opto/chaitin.cpp | 2 +- hotspot/src/share/vm/opto/gcm.cpp | 18 +++++------ hotspot/src/share/vm/opto/ifg.cpp | 10 +++++-- hotspot/src/share/vm/runtime/vmStructs.cpp | 4 +-- 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java index 156e8def9ca..519eeef4e61 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java @@ -48,7 +48,7 @@ public class Block extends VMObject { preOrderField = new CIntField(type.getCIntegerField("_pre_order"), 0); domDepthField = new CIntField(type.getCIntegerField("_dom_depth"), 0); idomField = type.getAddressField("_idom"); - freqField = type.getJFloatField("_freq"); + freqField = type.getJDoubleField("_freq"); } private static AddressField nodesField; @@ -57,7 +57,7 @@ public class Block extends VMObject { private static CIntField preOrderField; private static CIntField domDepthField; private static AddressField idomField; - private static JFloatField freqField; + private static JDoubleField freqField; public Block(Address addr) { super(addr); @@ -67,8 +67,8 @@ public class Block extends VMObject { return (int)preOrderField.getValue(getAddress()); } - public float freq() { - return (float)freqField.getValue(getAddress()); + public double freq() { + return (double)freqField.getValue(getAddress()); } public Node_List nodes() { diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index d085b29df3e..48aa6eeb25d 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -90,9 +90,9 @@ public: class CFGElement : public ResourceObj { friend class VMStructs; public: - float _freq; // Execution frequency (estimate) + double _freq; // Execution frequency (estimate) - CFGElement() : _freq(0.0f) {} + CFGElement() : _freq(0.0) {} virtual bool is_block() { return false; } virtual bool is_loop() { return false; } Block* as_Block() { assert(is_block(), "must be block"); return (Block*)this; } @@ -202,7 +202,7 @@ public: // BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies. // It is currently also used to scale such frequencies relative to // FreqCountInvocations relative to the old value of 1500. -#define BLOCK_FREQUENCY(f) ((f * (float) 1500) / FreqCountInvocations) +#define BLOCK_FREQUENCY(f) ((f * (double) 1500) / FreqCountInvocations) // Register Pressure (estimate) for Splitting heuristic uint _reg_pressure; @@ -393,7 +393,7 @@ class PhaseCFG : public Phase { CFGLoop* _root_loop; // Outmost loop frequency - float _outer_loop_frequency; + double _outer_loop_frequency; // Per node latency estimation, valid only during GCM GrowableArray* _node_latency; @@ -508,7 +508,7 @@ class PhaseCFG : public Phase { } // Get the outer most frequency - float get_outer_loop_frequency() const { + double get_outer_loop_frequency() const { return _outer_loop_frequency; } @@ -656,13 +656,13 @@ public: class BlockProbPair VALUE_OBJ_CLASS_SPEC { protected: Block* _target; // block target - float _prob; // probability of edge to block + double _prob; // probability of edge to block public: BlockProbPair() : _target(NULL), _prob(0.0) {} - BlockProbPair(Block* b, float p) : _target(b), _prob(p) {} + BlockProbPair(Block* b, double p) : _target(b), _prob(p) {} Block* get_target() const { return _target; } - float get_prob() const { return _prob; } + double get_prob() const { return _prob; } }; //------------------------------CFGLoop------------------------------------------- @@ -675,8 +675,8 @@ class CFGLoop : public CFGElement { CFGLoop *_child; // first child, use child's sibling to visit all immediately nested loops GrowableArray _members; // list of members of loop GrowableArray _exits; // list of successor blocks and their probabilities - float _exit_prob; // probability any loop exit is taken on a single loop iteration - void update_succ_freq(Block* b, float freq); + double _exit_prob; // probability any loop exit is taken on a single loop iteration + void update_succ_freq(Block* b, double freq); public: CFGLoop(int id) : @@ -702,9 +702,9 @@ class CFGLoop : public CFGElement { void compute_loop_depth(int depth); void compute_freq(); // compute frequency with loop assuming head freq 1.0f void scale_freq(); // scale frequency by loop trip count (including outer loops) - float outer_loop_freq() const; // frequency of outer loop + double outer_loop_freq() const; // frequency of outer loop bool in_loop_nest(Block* b); - float trip_count() const { return 1.0f / _exit_prob; } + double trip_count() const { return 1.0 / _exit_prob; } virtual bool is_loop() { return true; } int id() { return _id; } @@ -723,7 +723,7 @@ class CFGEdge : public ResourceObj { private: Block * _from; // Source basic block Block * _to; // Destination basic block - float _freq; // Execution frequency (estimate) + double _freq; // Execution frequency (estimate) int _state; bool _infrequent; int _from_pct; @@ -742,13 +742,13 @@ class CFGEdge : public ResourceObj { interior // edge is interior to trace (could be backedge) }; - CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) : + CFGEdge(Block *from, Block *to, double freq, int from_pct, int to_pct) : _from(from), _to(to), _freq(freq), _from_pct(from_pct), _to_pct(to_pct), _state(open) { _infrequent = from_infrequent() || to_infrequent(); } - float freq() const { return _freq; } + double freq() const { return _freq; } Block* from() const { return _from; } Block* to () const { return _to; } int infrequent() const { return _infrequent; } diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 0f64bccd6ba..5a1040aac48 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -210,7 +210,7 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher) { NOT_PRODUCT( Compile::TracePhase t3("ctorChaitin", &_t_ctorChaitin, TimeCompiler); ) - _high_frequency_lrg = MIN2(float(OPTO_LRG_HIGH_FREQ), _cfg.get_outer_loop_frequency()); + _high_frequency_lrg = MIN2(double(OPTO_LRG_HIGH_FREQ), _cfg.get_outer_loop_frequency()); // Build a list of basic blocks, sorted by frequency _blks = NEW_RESOURCE_ARRAY(Block *, _cfg.number_of_blocks()); diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index bd9a0304181..fcfb3880e19 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1661,10 +1661,10 @@ void CFGLoop::compute_freq() { } assert (_members.length() > 0, "no empty loops"); Block* hd = head(); - hd->_freq = 1.0f; + hd->_freq = 1.0; for (int i = 0; i < _members.length(); i++) { CFGElement* s = _members.at(i); - float freq = s->_freq; + double freq = s->_freq; if (s->is_block()) { Block* b = s->as_Block(); for (uint j = 0; j < b->_num_succs; j++) { @@ -1676,7 +1676,7 @@ void CFGLoop::compute_freq() { assert(lp->_parent == this, "immediate child"); for (int k = 0; k < lp->_exits.length(); k++) { Block* eb = lp->_exits.at(k).get_target(); - float prob = lp->_exits.at(k).get_prob(); + double prob = lp->_exits.at(k).get_prob(); update_succ_freq(eb, freq * prob); } } @@ -1688,7 +1688,7 @@ void CFGLoop::compute_freq() { // inner blocks do not get erroneously scaled. if (_depth != 0) { // Total the exit probabilities for this loop. - float exits_sum = 0.0f; + double exits_sum = 0.0f; for (int i = 0; i < _exits.length(); i++) { exits_sum += _exits.at(i).get_prob(); } @@ -1935,7 +1935,7 @@ void Block::update_uncommon_branch(Block* ub) { //------------------------------update_succ_freq------------------------------- // Update the appropriate frequency associated with block 'b', a successor of // a block in this loop. -void CFGLoop::update_succ_freq(Block* b, float freq) { +void CFGLoop::update_succ_freq(Block* b, double freq) { if (b->_loop == this) { if (b == head()) { // back branch within the loop @@ -1976,11 +1976,11 @@ bool CFGLoop::in_loop_nest(Block* b) { // Scale frequency of loops and blocks by trip counts from outer loops // Do a top down traversal of loop tree (visit outer loops first.) void CFGLoop::scale_freq() { - float loop_freq = _freq * trip_count(); + double loop_freq = _freq * trip_count(); _freq = loop_freq; for (int i = 0; i < _members.length(); i++) { CFGElement* s = _members.at(i); - float block_freq = s->_freq * loop_freq; + double block_freq = s->_freq * loop_freq; if (g_isnan(block_freq) || block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY; s->_freq = block_freq; @@ -1993,7 +1993,7 @@ void CFGLoop::scale_freq() { } // Frequency of outer loop -float CFGLoop::outer_loop_freq() const { +double CFGLoop::outer_loop_freq() const { if (_child != NULL) { return _child->_freq; } @@ -2042,7 +2042,7 @@ void CFGLoop::dump() const { k = 0; } Block *blk = _exits.at(i).get_target(); - float prob = _exits.at(i).get_prob(); + double prob = _exits.at(i).get_prob(); tty->print(" ->%d@%d%%", blk->_pre_order, (int)(prob*100)); } tty->print("\n"); diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 4b102d68589..b84ea45abb7 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -693,7 +693,7 @@ void PhaseChaitin::add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, do assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } - assert(!(lrg._area < 0.0), "negative spill area" ); + assert(lrg._area >= 0.0, "negative spill area" ); } } @@ -762,7 +762,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { int inst_count = last_inst - first_inst; double cost = (inst_count <= 0) ? 0.0 : block->_freq * double(inst_count); - assert(!(cost < 0.0), "negative spill cost" ); + assert(cost >= 0.0, "negative spill cost" ); compute_initial_block_pressure(block, &liveout, int_pressure, float_pressure, cost); @@ -789,7 +789,11 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { } } else { // A live range ends at its definition, remove the remaining area. - lrg._area -= cost; + // If the cost is +Inf (which might happen in extreme cases), the lrg area will also be +Inf, + // and +Inf - +Inf = NaN. So let's not do that subtraction. + if (g_isfinite(cost)) { + lrg._area -= cost; + } assert(lrg._area >= 0.0, "negative spill area" ); assign_high_score_to_immediate_copies(block, n, lrg, location + 1, last_inst); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 0fd2d70881f..7044dc9b2b7 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1176,9 +1176,9 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; c2_nonstatic_field(Block, _pre_order, uint) \ c2_nonstatic_field(Block, _dom_depth, uint) \ c2_nonstatic_field(Block, _idom, Block*) \ - c2_nonstatic_field(Block, _freq, jfloat) \ + c2_nonstatic_field(Block, _freq, jdouble) \ \ - c2_nonstatic_field(CFGElement, _freq, jfloat) \ + c2_nonstatic_field(CFGElement, _freq, jdouble) \ \ c2_nonstatic_field(Block_List, _cnt, uint) \ \ From 493557fc9099ffe12d8baa9a89e7ad3a61ed8378 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Tue, 25 Feb 2014 18:16:24 +0100 Subject: [PATCH 194/265] 8031752: Failed speculative optimizations should be reattempted when root of compilation is different Support for speculative traps that keep track of the root of the compilation in which a trap occurs. Reviewed-by: kvn, twisti --- hotspot/src/share/vm/ci/ciClassList.hpp | 1 + hotspot/src/share/vm/ci/ciMethodData.cpp | 149 +++++-- hotspot/src/share/vm/ci/ciMethodData.hpp | 58 ++- .../share/vm/interpreter/bytecodeTracer.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 10 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 2 +- hotspot/src/share/vm/oops/methodData.cpp | 406 +++++++++++++++--- hotspot/src/share/vm/oops/methodData.hpp | 135 ++++-- hotspot/src/share/vm/opto/compile.cpp | 10 +- hotspot/src/share/vm/opto/doCall.cpp | 2 +- hotspot/src/share/vm/opto/graphKit.cpp | 23 +- hotspot/src/share/vm/opto/graphKit.hpp | 2 +- .../src/share/vm/runtime/deoptimization.cpp | 18 +- .../src/share/vm/runtime/deoptimization.hpp | 15 + hotspot/src/share/vm/runtime/globals.hpp | 6 + .../TestSpecTrapClassUnloading.java | 97 +++++ 16 files changed, 772 insertions(+), 164 deletions(-) create mode 100644 hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java diff --git a/hotspot/src/share/vm/ci/ciClassList.hpp b/hotspot/src/share/vm/ci/ciClassList.hpp index ee82685a4df..1e6816030f7 100644 --- a/hotspot/src/share/vm/ci/ciClassList.hpp +++ b/hotspot/src/share/vm/ci/ciClassList.hpp @@ -103,6 +103,7 @@ friend class ciMethodHandle; \ friend class ciMethodType; \ friend class ciReceiverTypeData; \ friend class ciTypeEntries; \ +friend class ciSpeculativeTrapData; \ friend class ciSymbol; \ friend class ciArray; \ friend class ciObjArray; \ diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index 025146885db..950e3d6dd21 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -78,6 +78,35 @@ ciMethodData::ciMethodData() : ciMetadata(NULL) { _parameters = NULL; } +void ciMethodData::load_extra_data() { + MethodData* mdo = get_MethodData(); + + // speculative trap entries also hold a pointer to a Method so need to be translated + DataLayout* dp_src = mdo->extra_data_base(); + DataLayout* end_src = mdo->extra_data_limit(); + DataLayout* dp_dst = extra_data_base(); + for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) { + assert(dp_src < end_src, "moved past end of extra data"); + assert(dp_src->tag() == dp_dst->tag(), err_msg("should be same tags %d != %d", dp_src->tag(), dp_dst->tag())); + switch(dp_src->tag()) { + case DataLayout::speculative_trap_data_tag: { + ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); + SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); + data_dst->translate_from(data_src); + break; + } + case DataLayout::bit_data_tag: + break; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + // An empty slot or ArgInfoData entry marks the end of the trap data + return; + default: + fatal(err_msg("bad tag = %d", dp_src->tag())); + } + } +} + void ciMethodData::load_data() { MethodData* mdo = get_MethodData(); if (mdo == NULL) { @@ -116,6 +145,8 @@ void ciMethodData::load_data() { parameters->translate_from(mdo->parameters_type_data()); } + load_extra_data(); + // Note: Extra data are all BitData, and do not need translation. _current_mileage = MethodData::mileage_of(mdo->method()); _invocation_counter = mdo->invocation_count(); @@ -156,6 +187,12 @@ void ciReturnTypeEntry::translate_type_data_from(const ReturnTypeEntry* ret) { set_type(translate_klass(k)); } +void ciSpeculativeTrapData::translate_from(const ProfileData* data) { + Method* m = data->as_SpeculativeTrapData()->method(); + ciMethod* ci_m = CURRENT_ENV->get_method(m); + set_method(ci_m); +} + // Get the data at an arbitrary (sort of) data index. ciProfileData* ciMethodData::data_at(int data_index) { if (out_of_bounds(data_index)) { @@ -203,33 +240,65 @@ ciProfileData* ciMethodData::next_data(ciProfileData* current) { return next; } -// Translate a bci to its corresponding data, or NULL. -ciProfileData* ciMethodData::bci_to_data(int bci) { - ciProfileData* data = data_before(bci); - for ( ; is_valid(data); data = next_data(data)) { - if (data->bci() == bci) { - set_hint_di(dp_to_di(data->dp())); - return data; - } else if (data->bci() > bci) { - break; - } - } +ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) { // bci_to_extra_data(bci) ... DataLayout* dp = data_layout_at(data_size()); DataLayout* end = data_layout_at(data_size() + extra_data_size()); - for (; dp < end; dp = MethodData::next_extra(dp)) { - if (dp->tag() == DataLayout::no_tag) { + two_free_slots = false; + for (;dp < end; dp = MethodData::next_extra(dp)) { + switch(dp->tag()) { + case DataLayout::no_tag: _saw_free_extra_data = true; // observed an empty slot (common case) + two_free_slots = (MethodData::next_extra(dp)->tag() == DataLayout::no_tag); return NULL; + case DataLayout::arg_info_data_tag: + return NULL; // ArgInfoData is at the end of extra data section. + case DataLayout::bit_data_tag: + if (m == NULL && dp->bci() == bci) { + return new ciBitData(dp); + } + break; + case DataLayout::speculative_trap_data_tag: { + ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp); + // data->method() might be null if the MDO is snapshotted + // concurrently with a trap + if (m != NULL && data->method() == m && dp->bci() == bci) { + return data; + } + break; } - if (dp->tag() == DataLayout::arg_info_data_tag) { - break; // ArgInfoData is at the end of extra data section. + default: + fatal(err_msg("bad tag = %d", dp->tag())); } - if (dp->bci() == bci) { - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); - return new ciBitData(dp); + } + return NULL; +} + +// Translate a bci to its corresponding data, or NULL. +ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) { + // If m is not NULL we look for a SpeculativeTrapData entry + if (m == NULL) { + ciProfileData* data = data_before(bci); + for ( ; is_valid(data); data = next_data(data)) { + if (data->bci() == bci) { + set_hint_di(dp_to_di(data->dp())); + return data; + } else if (data->bci() > bci) { + break; + } } } + bool two_free_slots = false; + ciProfileData* result = bci_to_extra_data(bci, m, two_free_slots); + if (result != NULL) { + return result; + } + if (m != NULL && !two_free_slots) { + // We were looking for a SpeculativeTrapData entry we didn't + // find. Room is not available for more SpeculativeTrapData + // entries, look in the non SpeculativeTrapData entries. + return bci_to_data(bci, NULL); + } return NULL; } @@ -525,18 +594,25 @@ void ciMethodData::print_data_on(outputStream* st) { st->print_cr("--- Extra data:"); DataLayout* dp = data_layout_at(data_size()); DataLayout* end = data_layout_at(data_size() + extra_data_size()); - for (; dp < end; dp = MethodData::next_extra(dp)) { - if (dp->tag() == DataLayout::no_tag) continue; - if (dp->tag() == DataLayout::bit_data_tag) { + for (;; dp = MethodData::next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); + switch (dp->tag()) { + case DataLayout::no_tag: + continue; + case DataLayout::bit_data_tag: data = new BitData(dp); - } else { - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); + break; + case DataLayout::arg_info_data_tag: data = new ciArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); } st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); + if (dp >= end) return; } } @@ -569,8 +645,8 @@ void ciReturnTypeEntry::print_data_on(outputStream* st) const { st->cr(); } -void ciCallTypeData::print_data_on(outputStream* st) const { - print_shared(st, "ciCallTypeData"); +void ciCallTypeData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ciCallTypeData", extra); if (has_arguments()) { tab(st, true); st->print("argument types"); @@ -599,18 +675,18 @@ void ciReceiverTypeData::print_receiver_data_on(outputStream* st) const { } } -void ciReceiverTypeData::print_data_on(outputStream* st) const { - print_shared(st, "ciReceiverTypeData"); +void ciReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ciReceiverTypeData", extra); print_receiver_data_on(st); } -void ciVirtualCallData::print_data_on(outputStream* st) const { - print_shared(st, "ciVirtualCallData"); +void ciVirtualCallData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ciVirtualCallData", extra); rtd_super()->print_receiver_data_on(st); } -void ciVirtualCallTypeData::print_data_on(outputStream* st) const { - print_shared(st, "ciVirtualCallTypeData"); +void ciVirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ciVirtualCallTypeData", extra); rtd_super()->print_receiver_data_on(st); if (has_arguments()) { tab(st, true); @@ -624,8 +700,15 @@ void ciVirtualCallTypeData::print_data_on(outputStream* st) const { } } -void ciParametersTypeData::print_data_on(outputStream* st) const { - st->print_cr("Parametertypes"); +void ciParametersTypeData::print_data_on(outputStream* st, const char* extra) const { + st->print_cr("ciParametersTypeData"); parameters()->print_data_on(st); } + +void ciSpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { + st->print_cr("ciSpeculativeTrapData"); + tab(st); + method()->print_short_name(st); + st->cr(); +} #endif diff --git a/hotspot/src/share/vm/ci/ciMethodData.hpp b/hotspot/src/share/vm/ci/ciMethodData.hpp index f1a7f2634e4..e5b380fe70f 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.hpp +++ b/hotspot/src/share/vm/ci/ciMethodData.hpp @@ -31,6 +31,7 @@ #include "ci/ciUtilities.hpp" #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" +#include "runtime/deoptimization.hpp" class ciBitData; class ciCounterData; @@ -44,6 +45,7 @@ class ciArgInfoData; class ciCallTypeData; class ciVirtualCallTypeData; class ciParametersTypeData; +class ciSpeculativeTrapData;; typedef ProfileData ciProfileData; @@ -173,7 +175,7 @@ public: } #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra) const; #endif }; @@ -200,7 +202,7 @@ public: } void translate_receiver_data_from(const ProfileData* data); #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra) const; void print_receiver_data_on(outputStream* st) const; #endif }; @@ -225,7 +227,7 @@ public: rtd_super()->translate_receiver_data_from(data); } #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra) const; #endif }; @@ -287,7 +289,7 @@ public: } #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra) const; #endif }; @@ -336,7 +338,26 @@ public: } #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra) const; +#endif +}; + +class ciSpeculativeTrapData : public SpeculativeTrapData { +public: + ciSpeculativeTrapData(DataLayout* layout) : SpeculativeTrapData(layout) {} + + virtual void translate_from(const ProfileData* data); + + ciMethod* method() const { + return (ciMethod*)intptr_at(method_offset); + } + + void set_method(ciMethod* m) { + set_intptr_at(method_offset, (intptr_t)m); + } + +#ifndef PRODUCT + void print_data_on(outputStream* st, const char* extra) const; #endif }; @@ -436,6 +457,16 @@ private: ciArgInfoData *arg_info() const; + address data_base() const { + return (address) _data; + } + DataLayout* limit_data_position() const { + return (DataLayout*)((address)data_base() + _data_size); + } + + void load_extra_data(); + ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots); + public: bool is_method_data() const { return true; } @@ -475,9 +506,11 @@ public: ciProfileData* next_data(ciProfileData* current); bool is_valid(ciProfileData* current) { return current != NULL; } - // Get the data at an arbitrary bci, or NULL if there is none. - ciProfileData* bci_to_data(int bci); - ciProfileData* bci_to_extra_data(int bci, bool create_if_missing); + DataLayout* extra_data_base() const { return limit_data_position(); } + + // Get the data at an arbitrary bci, or NULL if there is none. If m + // is not NULL look for a SpeculativeTrapData if any first. + ciProfileData* bci_to_data(int bci, ciMethod* m = NULL); uint overflow_trap_count() const { return _orig.overflow_trap_count(); @@ -496,12 +529,13 @@ public: // Helpful query functions that decode trap_state. int has_trap_at(ciProfileData* data, int reason); - int has_trap_at(int bci, int reason) { - return has_trap_at(bci_to_data(bci), reason); + int has_trap_at(int bci, ciMethod* m, int reason) { + assert((m != NULL) == Deoptimization::reason_is_speculate(reason), "inconsistent method/reason"); + return has_trap_at(bci_to_data(bci, m), reason); } int trap_recompiled_at(ciProfileData* data); - int trap_recompiled_at(int bci) { - return trap_recompiled_at(bci_to_data(bci)); + int trap_recompiled_at(int bci, ciMethod* m) { + return trap_recompiled_at(bci_to_data(bci, m)); } void clear_escape_info(); diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp index 37ac6d1a6e4..1892940f216 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp @@ -596,7 +596,7 @@ void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) { if (data != NULL) { st->print(" %d", mdo->dp_to_di(data->dp())); st->fill_to(6); - data->print_data_on(st); + data->print_data_on(st, mdo); } } } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 62f7ffbf370..7dee4f3dba3 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2192,15 +2192,7 @@ void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) { for (int m = 0; m < methods()->length(); m++) { MethodData* mdo = methods()->at(m)->method_data(); if (mdo != NULL) { - for (ProfileData* data = mdo->first_data(); - mdo->is_valid(data); - data = mdo->next_data(data)) { - data->clean_weak_klass_links(is_alive); - } - ParametersTypeData* parameters = mdo->parameters_type_data(); - if (parameters != NULL) { - parameters->clean_weak_klass_links(is_alive); - } + mdo->clean_method_data(is_alive); } } } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index db14be29a14..b25c75afc3b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -306,7 +306,7 @@ class InstanceKlass: public Klass { // three cases: // NULL: no implementor. // A Klass* that's not itself: one implementor. - // Itsef: more than one implementors. + // Itself: more than one implementors. // embedded host klass follows here // The embedded host klass only exists in an anonymous class for // dynamic language support (JSR 292 enabled). The host class grants diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 2da63c08d8c..b226173d832 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -80,8 +80,42 @@ ProfileData::ProfileData() { _data = NULL; } +char* ProfileData::print_data_on_helper(const MethodData* md) const { + DataLayout* dp = md->extra_data_base(); + DataLayout* end = md->extra_data_limit(); + stringStream ss; + for (;; dp = MethodData::next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); + switch(dp->tag()) { + case DataLayout::speculative_trap_data_tag: + if (dp->bci() == bci()) { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + int trap = data->trap_state(); + char buf[100]; + ss.print("trap/"); + data->method()->print_short_name(&ss); + ss.print("(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); + } + break; + case DataLayout::bit_data_tag: + break; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + return ss.as_string(); + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } + return NULL; +} + +void ProfileData::print_data_on(outputStream* st, const MethodData* md) const { + print_data_on(st, print_data_on_helper(md)); +} + #ifndef PRODUCT -void ProfileData::print_shared(outputStream* st, const char* name) const { +void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const { st->print("bci: %d", bci()); st->fill_to(tab_width_one); st->print("%s", name); @@ -91,9 +125,13 @@ void ProfileData::print_shared(outputStream* st, const char* name) const { char buf[100]; st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); } + if (extra != NULL) { + st->print(extra); + } int flags = data()->flags(); - if (flags != 0) + if (flags != 0) { st->print("flags(%d) ", flags); + } } void ProfileData::tab(outputStream* st, bool first) const { @@ -109,8 +147,8 @@ void ProfileData::tab(outputStream* st, bool first) const { #ifndef PRODUCT -void BitData::print_data_on(outputStream* st) const { - print_shared(st, "BitData"); +void BitData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "BitData", extra); } #endif // !PRODUCT @@ -120,8 +158,8 @@ void BitData::print_data_on(outputStream* st) const { // A CounterData corresponds to a simple counter. #ifndef PRODUCT -void CounterData::print_data_on(outputStream* st) const { - print_shared(st, "CounterData"); +void CounterData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "CounterData", extra); st->print_cr("count(%u)", count()); } #endif // !PRODUCT @@ -150,8 +188,8 @@ void JumpData::post_initialize(BytecodeStream* stream, MethodData* mdo) { } #ifndef PRODUCT -void JumpData::print_data_on(outputStream* st) const { - print_shared(st, "JumpData"); +void JumpData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "JumpData", extra); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); } #endif // !PRODUCT @@ -332,8 +370,8 @@ void ReturnTypeEntry::print_data_on(outputStream* st) const { st->cr(); } -void CallTypeData::print_data_on(outputStream* st) const { - CounterData::print_data_on(st); +void CallTypeData::print_data_on(outputStream* st, const char* extra) const { + CounterData::print_data_on(st, extra); if (has_arguments()) { tab(st, true); st->print("argument types"); @@ -346,8 +384,8 @@ void CallTypeData::print_data_on(outputStream* st) const { } } -void VirtualCallTypeData::print_data_on(outputStream* st) const { - VirtualCallData::print_data_on(st); +void VirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { + VirtualCallData::print_data_on(st, extra); if (has_arguments()) { tab(st, true); st->print("argument types"); @@ -400,12 +438,12 @@ void ReceiverTypeData::print_receiver_data_on(outputStream* st) const { } } } -void ReceiverTypeData::print_data_on(outputStream* st) const { - print_shared(st, "ReceiverTypeData"); +void ReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ReceiverTypeData", extra); print_receiver_data_on(st); } -void VirtualCallData::print_data_on(outputStream* st) const { - print_shared(st, "VirtualCallData"); +void VirtualCallData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "VirtualCallData", extra); print_receiver_data_on(st); } #endif // !PRODUCT @@ -461,8 +499,8 @@ DataLayout* RetData::advance(MethodData *md, int bci) { #endif // CC_INTERP #ifndef PRODUCT -void RetData::print_data_on(outputStream* st) const { - print_shared(st, "RetData"); +void RetData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "RetData", extra); uint row; int entries = 0; for (row = 0; row < row_limit(); row++) { @@ -496,8 +534,8 @@ void BranchData::post_initialize(BytecodeStream* stream, MethodData* mdo) { } #ifndef PRODUCT -void BranchData::print_data_on(outputStream* st) const { - print_shared(st, "BranchData"); +void BranchData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "BranchData", extra); st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); tab(st); @@ -570,8 +608,8 @@ void MultiBranchData::post_initialize(BytecodeStream* stream, } #ifndef PRODUCT -void MultiBranchData::print_data_on(outputStream* st) const { - print_shared(st, "MultiBranchData"); +void MultiBranchData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "MultiBranchData", extra); st->print_cr("default_count(%u) displacement(%d)", default_count(), default_displacement()); int cases = number_of_cases(); @@ -584,8 +622,8 @@ void MultiBranchData::print_data_on(outputStream* st) const { #endif #ifndef PRODUCT -void ArgInfoData::print_data_on(outputStream* st) const { - print_shared(st, "ArgInfoData"); +void ArgInfoData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "ArgInfoData", extra); int nargs = number_of_args(); for (int i = 0; i < nargs; i++) { st->print(" 0x%x", arg_modified(i)); @@ -616,10 +654,17 @@ bool ParametersTypeData::profiling_enabled() { } #ifndef PRODUCT -void ParametersTypeData::print_data_on(outputStream* st) const { - st->print("parameter types"); +void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const { + st->print("parameter types", extra); _parameters.print_data_on(st); } + +void SpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { + print_shared(st, "SpeculativeTrapData", extra); + tab(st); + method()->print_short_name(st); + st->cr(); +} #endif // ================================================================== @@ -745,7 +790,27 @@ int MethodData::compute_data_size(BytecodeStream* stream) { return DataLayout::compute_size_in_bytes(cell_count); } -int MethodData::compute_extra_data_count(int data_size, int empty_bc_count) { +bool MethodData::is_speculative_trap_bytecode(Bytecodes::Code code) { + // Bytecodes for which we may use speculation + switch (code) { + case Bytecodes::_checkcast: + case Bytecodes::_instanceof: + case Bytecodes::_aastore: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + case Bytecodes::_if_acmpeq: + case Bytecodes::_if_acmpne: + case Bytecodes::_invokestatic: +#ifdef COMPILER2 + return UseTypeSpeculation; +#endif + default: + return false; + } + return false; +} + +int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) { if (ProfileTraps) { // Assume that up to 3% of BCIs with no MDP will need to allocate one. int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; @@ -756,7 +821,18 @@ int MethodData::compute_extra_data_count(int data_size, int empty_bc_count) { extra_data_count = one_percent_of_data; if (extra_data_count > empty_bc_count) extra_data_count = empty_bc_count; // no need for more - return extra_data_count; + + // Make sure we have a minimum number of extra data slots to + // allocate SpeculativeTrapData entries. We would want to have one + // entry per compilation that inlines this method and for which + // some type speculation assumption fails. So the room we need for + // the SpeculativeTrapData entries doesn't directly depend on the + // size of the method. Because it's hard to estimate, we reserve + // space for an arbitrary number of entries. + int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) * + (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells()); + + return MAX2(extra_data_count, spec_data_count); } else { return 0; } @@ -769,15 +845,17 @@ int MethodData::compute_allocation_size_in_bytes(methodHandle method) { BytecodeStream stream(method); Bytecodes::Code c; int empty_bc_count = 0; // number of bytecodes lacking data + bool needs_speculative_traps = false; while ((c = stream.next()) >= 0) { int size_in_bytes = compute_data_size(&stream); data_size += size_in_bytes; if (size_in_bytes == 0) empty_bc_count += 1; + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); } int object_size = in_bytes(data_offset()) + data_size; // Add some extra DataLayout cells (at least one) to track stray traps. - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); // Add a cell to record information about modified arguments. @@ -1009,18 +1087,23 @@ MethodData::MethodData(methodHandle method, int size, TRAPS) { _data[0] = 0; // apparently not set below. BytecodeStream stream(method); Bytecodes::Code c; + bool needs_speculative_traps = false; while ((c = stream.next()) >= 0) { int size_in_bytes = initialize_data(&stream, data_size); data_size += size_in_bytes; if (size_in_bytes == 0) empty_bc_count += 1; + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); } _data_size = data_size; int object_size = in_bytes(data_offset()) + data_size; // Add some extra DataLayout cells (at least one) to track stray traps. - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); + // Let's zero the space for the extra data + Copy::zero_to_bytes(((address)_data) + data_size, extra_size); + // Add a cell to record information about modified arguments. // Set up _args_modified array after traps cells so that // the code for traps cells works. @@ -1032,17 +1115,17 @@ MethodData::MethodData(methodHandle method, int size, TRAPS) { int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); object_size += extra_size + arg_data_size; - int args_cell = ParametersTypeData::compute_cell_count(method()); + int parms_cell = ParametersTypeData::compute_cell_count(method()); // If we are profiling parameters, we reserver an area near the end // of the MDO after the slots for bytecodes (because there's no bci // for method entry so they don't fit with the framework for the // profiling of bytecodes). We store the offset within the MDO of // this area (or -1 if no parameter is profiled) - if (args_cell > 0) { - object_size += DataLayout::compute_size_in_bytes(args_cell); + if (parms_cell > 0) { + object_size += DataLayout::compute_size_in_bytes(parms_cell); _parameters_type_data_di = data_size + extra_size + arg_data_size; DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); - dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); + dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell); } else { _parameters_type_data_di = -1; } @@ -1133,39 +1216,113 @@ ProfileData* MethodData::bci_to_data(int bci) { break; } } - return bci_to_extra_data(bci, false); + return bci_to_extra_data(bci, NULL, false); } -// Translate a bci to its corresponding extra data, or NULL. -ProfileData* MethodData::bci_to_extra_data(int bci, bool create_if_missing) { - DataLayout* dp = extra_data_base(); - DataLayout* end = extra_data_limit(); - DataLayout* avail = NULL; - for (; dp < end; dp = next_extra(dp)) { +DataLayout* MethodData::next_extra(DataLayout* dp) { + int nb_cells = 0; + switch(dp->tag()) { + case DataLayout::bit_data_tag: + case DataLayout::no_tag: + nb_cells = BitData::static_cell_count(); + break; + case DataLayout::speculative_trap_data_tag: + nb_cells = SpeculativeTrapData::static_cell_count(); + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + return (DataLayout*)((address)dp + DataLayout::compute_size_in_bytes(nb_cells)); +} + +ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp) { + DataLayout* end = extra_data_limit(); + + for (;; dp = next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. - if (dp->tag() == DataLayout::no_tag) break; - if (dp->tag() == DataLayout::arg_info_data_tag) { - dp = end; // ArgInfoData is at the end of extra data section. + switch(dp->tag()) { + case DataLayout::no_tag: + return NULL; + case DataLayout::arg_info_data_tag: + dp = end; + return NULL; // ArgInfoData is at the end of extra data section. + case DataLayout::bit_data_tag: + if (m == NULL && dp->bci() == bci) { + return new BitData(dp); + } break; - } - if (dp->bci() == bci) { - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); - return new BitData(dp); + case DataLayout::speculative_trap_data_tag: + if (m != NULL) { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + // data->method() may be null in case of a concurrent + // allocation. Assume it's for the same method and use that + // entry in that case. + if (dp->bci() == bci) { + if (data->method() == NULL) { + return NULL; + } else if (data->method() == m) { + return data; + } + } + } + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); } } - if (create_if_missing && dp < end) { - // Allocate this one. There is no mutual exclusion, - // so two threads could allocate different BCIs to the - // same data layout. This means these extra data - // records, like most other MDO contents, must not be - // trusted too much. - DataLayout temp; - temp.initialize(DataLayout::bit_data_tag, bci, 0); - dp->release_set_header(temp.header()); - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); - //NO: assert(dp->bci() == bci, "no concurrent allocation"); - return new BitData(dp); + return NULL; +} + + +// Translate a bci to its corresponding extra data, or NULL. +ProfileData* MethodData::bci_to_extra_data(int bci, Method* m, bool create_if_missing) { + // This code assumes an entry for a SpeculativeTrapData is 2 cells + assert(2*DataLayout::compute_size_in_bytes(BitData::static_cell_count()) == + DataLayout::compute_size_in_bytes(SpeculativeTrapData::static_cell_count()), + "code needs to be adjusted"); + + DataLayout* dp = extra_data_base(); + DataLayout* end = extra_data_limit(); + + // Allocation in the extra data space has to be atomic because not + // all entries have the same size and non atomic concurrent + // allocation would result in a corrupted extra data space. + while (true) { + ProfileData* result = bci_to_extra_data_helper(bci, m, dp); + if (result != NULL) { + return result; + } + + if (create_if_missing && dp < end) { + assert(dp->tag() == DataLayout::no_tag || (dp->tag() == DataLayout::speculative_trap_data_tag && m != NULL), "should be free"); + assert(next_extra(dp)->tag() == DataLayout::no_tag || next_extra(dp)->tag() == DataLayout::arg_info_data_tag, "should be free or arg info"); + u1 tag = m == NULL ? DataLayout::bit_data_tag : DataLayout::speculative_trap_data_tag; + // SpeculativeTrapData is 2 slots. Make sure we have room. + if (m != NULL && next_extra(dp)->tag() != DataLayout::no_tag) { + return NULL; + } + DataLayout temp; + temp.initialize(tag, bci, 0); + // May have been set concurrently + if (dp->header() != temp.header() && !dp->atomic_set_header(temp.header())) { + // Allocation failure because of concurrent allocation. Try + // again. + continue; + } + assert(dp->tag() == tag, "sane"); + assert(dp->bci() == bci, "no concurrent allocation"); + if (tag == DataLayout::bit_data_tag) { + return new BitData(dp); + } else { + // If being allocated concurrently, one trap may be lost + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + data->set_method(m); + return data; + } + } + return NULL; } return NULL; } @@ -1210,25 +1367,35 @@ void MethodData::print_data_on(outputStream* st) const { for ( ; is_valid(data); data = next_data(data)) { st->print("%d", dp_to_di(data->dp())); st->fill_to(6); - data->print_data_on(st); + data->print_data_on(st, this); } st->print_cr("--- Extra data:"); DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); - for (; dp < end; dp = next_extra(dp)) { + for (;; dp = next_extra(dp)) { + assert(dp < end, "moved past end of extra data"); // No need for "OrderAccess::load_acquire" ops, // since the data structure is monotonic. - if (dp->tag() == DataLayout::no_tag) continue; - if (dp->tag() == DataLayout::bit_data_tag) { + switch(dp->tag()) { + case DataLayout::no_tag: + continue; + case DataLayout::bit_data_tag: data = new BitData(dp); - } else { - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); + break; + case DataLayout::speculative_trap_data_tag: + data = new SpeculativeTrapData(dp); + break; + case DataLayout::arg_info_data_tag: data = new ArgInfoData(dp); dp = end; // ArgInfoData is at the end of extra data section. + break; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); } st->print("%d", dp_to_di(data->dp())); st->fill_to(6); data->print_data_on(st); + if (dp >= end) return; } } #endif @@ -1351,3 +1518,110 @@ bool MethodData::profile_parameters_for_method(methodHandle m) { assert(profile_parameters_jsr292_only(), "inconsistent"); return m->is_compiled_lambda_form(); } + +void MethodData::clean_extra_data_helper(DataLayout* dp, int shift, bool reset) { + if (shift == 0) { + return; + } + if (!reset) { + // Move all cells of trap entry at dp left by "shift" cells + intptr_t* start = (intptr_t*)dp; + intptr_t* end = (intptr_t*)next_extra(dp); + for (intptr_t* ptr = start; ptr < end; ptr++) { + *(ptr-shift) = *ptr; + } + } else { + // Reset "shift" cells stopping at dp + intptr_t* start = ((intptr_t*)dp) - shift; + intptr_t* end = (intptr_t*)dp; + for (intptr_t* ptr = start; ptr < end; ptr++) { + *ptr = 0; + } + } +} + +// Remove SpeculativeTrapData entries that reference an unloaded +// method +void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { + DataLayout* dp = extra_data_base(); + DataLayout* end = extra_data_limit(); + + int shift = 0; + for (; dp < end; dp = next_extra(dp)) { + switch(dp->tag()) { + case DataLayout::speculative_trap_data_tag: { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + Method* m = data->method(); + assert(m != NULL, "should have a method"); + if (!m->method_holder()->is_loader_alive(is_alive)) { + // "shift" accumulates the number of cells for dead + // SpeculativeTrapData entries that have been seen so + // far. Following entries must be shifted left by that many + // cells to remove the dead SpeculativeTrapData entries. + shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp); + } else { + // Shift this entry left if it follows dead + // SpeculativeTrapData entries + clean_extra_data_helper(dp, shift); + } + break; + } + case DataLayout::bit_data_tag: + // Shift this entry left if it follows dead SpeculativeTrapData + // entries + clean_extra_data_helper(dp, shift); + continue; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + // We are at end of the live trap entries. The previous "shift" + // cells contain entries that are either dead or were shifted + // left. They need to be reset to no_tag + clean_extra_data_helper(dp, shift, true); + return; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } +} + +// Verify there's no unloaded method referenced by a +// SpeculativeTrapData entry +void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { +#ifdef ASSERT + DataLayout* dp = extra_data_base(); + DataLayout* end = extra_data_limit(); + + for (; dp < end; dp = next_extra(dp)) { + switch(dp->tag()) { + case DataLayout::speculative_trap_data_tag: { + SpeculativeTrapData* data = new SpeculativeTrapData(dp); + Method* m = data->method(); + assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); + break; + } + case DataLayout::bit_data_tag: + continue; + case DataLayout::no_tag: + case DataLayout::arg_info_data_tag: + return; + default: + fatal(err_msg("unexpected tag %d", dp->tag())); + } + } +#endif +} + +void MethodData::clean_method_data(BoolObjectClosure* is_alive) { + for (ProfileData* data = first_data(); + is_valid(data); + data = next_data(data)) { + data->clean_weak_klass_links(is_alive); + } + ParametersTypeData* parameters = parameters_type_data(); + if (parameters != NULL) { + parameters->clean_weak_klass_links(is_alive); + } + + clean_extra_data(is_alive); + verify_extra_data_clean(is_alive); +} diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 57790371e7c..76b0708f233 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -120,7 +120,8 @@ public: arg_info_data_tag, call_type_data_tag, virtual_call_type_data_tag, - parameters_type_data_tag + parameters_type_data_tag, + speculative_trap_data_tag }; enum { @@ -189,8 +190,11 @@ public: void set_header(intptr_t value) { _header._bits = value; } - void release_set_header(intptr_t value) { - OrderAccess::release_store_ptr(&_header._bits, value); + bool atomic_set_header(intptr_t value) { + if (Atomic::cmpxchg_ptr(value, (volatile intptr_t*)&_header._bits, 0) == 0) { + return true; + } + return false; } intptr_t header() { return _header._bits; @@ -271,6 +275,7 @@ class ArrayData; class MultiBranchData; class ArgInfoData; class ParametersTypeData; +class SpeculativeTrapData; // ProfileData // @@ -291,6 +296,8 @@ private: // This is a pointer to a section of profiling data. DataLayout* _data; + char* print_data_on_helper(const MethodData* md) const; + protected: DataLayout* data() { return _data; } const DataLayout* data() const { return _data; } @@ -440,6 +447,7 @@ public: virtual bool is_CallTypeData() const { return false; } virtual bool is_VirtualCallTypeData()const { return false; } virtual bool is_ParametersTypeData() const { return false; } + virtual bool is_SpeculativeTrapData()const { return false; } BitData* as_BitData() const { @@ -494,6 +502,10 @@ public: assert(is_ParametersTypeData(), "wrong type"); return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL; } + SpeculativeTrapData* as_SpeculativeTrapData() const { + assert(is_SpeculativeTrapData(), "wrong type"); + return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : NULL; + } // Subclass specific initialization @@ -509,12 +521,14 @@ public: // translation here, and the required translators are in the ci subclasses. virtual void translate_from(const ProfileData* data) {} - virtual void print_data_on(outputStream* st) const { + virtual void print_data_on(outputStream* st, const char* extra = NULL) const { ShouldNotReachHere(); } + void print_data_on(outputStream* st, const MethodData* md) const; + #ifndef PRODUCT - void print_shared(outputStream* st, const char* name) const; + void print_shared(outputStream* st, const char* name, const char* extra) const; void tab(outputStream* st, bool first = false) const; #endif }; @@ -576,7 +590,7 @@ public: #endif // CC_INTERP #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -639,7 +653,7 @@ public: #endif // CC_INTERP #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -726,7 +740,7 @@ public: void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1137,7 +1151,7 @@ public: } #ifndef PRODUCT - virtual void print_data_on(outputStream* st) const; + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1282,7 +1296,7 @@ public: #ifndef PRODUCT void print_receiver_data_on(outputStream* st) const; - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1325,7 +1339,7 @@ public: #endif // CC_INTERP #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1451,7 +1465,7 @@ public: } #ifndef PRODUCT - virtual void print_data_on(outputStream* st) const; + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1554,7 +1568,7 @@ public: void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1632,7 +1646,7 @@ public: void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1825,7 +1839,7 @@ public: void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1852,7 +1866,7 @@ public: } #ifndef PRODUCT - void print_data_on(outputStream* st) const; + void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; @@ -1913,7 +1927,7 @@ public: } #ifndef PRODUCT - virtual void print_data_on(outputStream* st) const; + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif static ByteSize stack_slot_offset(int i) { @@ -1925,6 +1939,54 @@ public: } }; +// SpeculativeTrapData +// +// A SpeculativeTrapData is used to record traps due to type +// speculation. It records the root of the compilation: that type +// speculation is wrong in the context of one compilation (for +// method1) doesn't mean it's wrong in the context of another one (for +// method2). Type speculation could have more/different data in the +// context of the compilation of method2 and it's worthwhile to try an +// optimization that failed for compilation of method1 in the context +// of compilation of method2. +// Space for SpeculativeTrapData entries is allocated from the extra +// data space in the MDO. If we run out of space, the trap data for +// the ProfileData at that bci is updated. +class SpeculativeTrapData : public ProfileData { +protected: + enum { + method_offset, + speculative_trap_cell_count + }; +public: + SpeculativeTrapData(DataLayout* layout) : ProfileData(layout) { + assert(layout->tag() == DataLayout::speculative_trap_data_tag, "wrong type"); + } + + virtual bool is_SpeculativeTrapData() const { return true; } + + static int static_cell_count() { + return speculative_trap_cell_count; + } + + virtual int cell_count() const { + return static_cell_count(); + } + + // Direct accessor + Method* method() const { + return (Method*)intptr_at(method_offset); + } + + void set_method(Method* m) { + set_intptr_at(method_offset, (intptr_t)m); + } + +#ifndef PRODUCT + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; +#endif +}; + // MethodData* // // A MethodData* holds information which has been collected about @@ -1994,7 +2056,7 @@ public: // Whole-method sticky bits and flags enum { - _trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT + _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values @@ -2049,6 +2111,7 @@ private: // Helper for size computation static int compute_data_size(BytecodeStream* stream); static int bytecode_cell_count(Bytecodes::Code code); + static bool is_speculative_trap_bytecode(Bytecodes::Code code); enum { no_profile_data = -1, variable_cell_count = -2 }; // Helper for initialization @@ -2092,8 +2155,9 @@ private: // What is the index of the first data entry? int first_di() const { return 0; } + ProfileData* bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp); // Find or create an extra ProfileData: - ProfileData* bci_to_extra_data(int bci, bool create_if_missing); + ProfileData* bci_to_extra_data(int bci, Method* m, bool create_if_missing); // return the argument info cell ArgInfoData *arg_info(); @@ -2116,6 +2180,10 @@ private: static bool profile_parameters_jsr292_only(); static bool profile_all_parameters(); + void clean_extra_data(BoolObjectClosure* is_alive); + void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); + void verify_extra_data_clean(BoolObjectClosure* is_alive); + public: static int header_size() { return sizeof(MethodData)/wordSize; @@ -2124,7 +2192,7 @@ public: // Compute the size of a MethodData* before it is created. static int compute_allocation_size_in_bytes(methodHandle method); static int compute_allocation_size_in_words(methodHandle method); - static int compute_extra_data_count(int data_size, int empty_bc_count); + static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps); // Determine if a given bytecode can have profile information. static bool bytecode_has_profile(Bytecodes::Code code) { @@ -2265,9 +2333,26 @@ public: ProfileData* bci_to_data(int bci); // Same, but try to create an extra_data record if one is needed: - ProfileData* allocate_bci_to_data(int bci) { - ProfileData* data = bci_to_data(bci); - return (data != NULL) ? data : bci_to_extra_data(bci, true); + ProfileData* allocate_bci_to_data(int bci, Method* m) { + ProfileData* data = NULL; + // If m not NULL, try to allocate a SpeculativeTrapData entry + if (m == NULL) { + data = bci_to_data(bci); + } + if (data != NULL) { + return data; + } + data = bci_to_extra_data(bci, m, true); + if (data != NULL) { + return data; + } + // If SpeculativeTrapData allocation fails try to allocate a + // regular entry + data = bci_to_data(bci); + if (data != NULL) { + return data; + } + return bci_to_extra_data(bci, NULL, true); } // Add a handful of extra data records, for trap tracking. @@ -2275,7 +2360,7 @@ public: DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); } int extra_data_size() const { return (address)extra_data_limit() - (address)extra_data_base(); } - static DataLayout* next_extra(DataLayout* dp) { return (DataLayout*)((address)dp + in_bytes(DataLayout::cell_offset(0))); } + static DataLayout* next_extra(DataLayout* dp); // Return (uint)-1 for overflow. uint trap_count(int reason) const { @@ -2375,6 +2460,8 @@ public: static bool profile_return(); static bool profile_parameters(); static bool profile_return_jsr292_only(); + + void clean_method_data(BoolObjectClosure* is_alive); }; #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index f3b798296f4..47acd4c5b49 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3249,7 +3249,8 @@ bool Compile::too_many_traps(ciMethod* method, // because of a transient condition during start-up in the interpreter. return false; } - if (md->has_trap_at(bci, reason) != 0) { + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; + if (md->has_trap_at(bci, m, reason) != 0) { // Assume PerBytecodeTrapLimit==0, for a more conservative heuristic. // Also, if there are multiple reasons, or if there is no per-BCI record, // assume the worst. @@ -3267,7 +3268,7 @@ bool Compile::too_many_traps(ciMethod* method, // Less-accurate variant which does not require a method and bci. bool Compile::too_many_traps(Deoptimization::DeoptReason reason, ciMethodData* logmd) { - if (trap_count(reason) >= (uint)PerMethodTrapLimit) { + if (trap_count(reason) >= Deoptimization::per_method_trap_limit(reason)) { // Too many traps globally. // Note that we use cumulative trap_count, not just md->trap_count. if (log()) { @@ -3302,10 +3303,11 @@ bool Compile::too_many_recompiles(ciMethod* method, uint m_cutoff = (uint) PerMethodRecompilationCutoff / 2 + 1; // not zero Deoptimization::DeoptReason per_bc_reason = Deoptimization::reason_recorded_per_bytecode_if_any(reason); + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; if ((per_bc_reason == Deoptimization::Reason_none - || md->has_trap_at(bci, reason) != 0) + || md->has_trap_at(bci, m, reason) != 0) // The trap frequency measure we care about is the recompile count: - && md->trap_recompiled_at(bci) + && md->trap_recompiled_at(bci, m) && md->overflow_recompile_count() >= bc_cutoff) { // Do not emit a trap here if it has already caused recompilations. // Also, if there are multiple reasons, or if there is no per-BCI record, diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index e888b550f66..d56f460ea6d 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -250,7 +250,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool CallGenerator* miss_cg; Deoptimization::DeoptReason reason = morphism == 2 ? Deoptimization::Reason_bimorphic : - Deoptimization::Reason_class_check; + (speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check); if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && !too_many_traps(jvms->method(), jvms->bci(), reason) ) { diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index af4b2f452a2..d2876a93a5e 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -612,9 +612,10 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) { // Usual case: Bail to interpreter. // Reserve the right to recompile if we haven't seen anything yet. + assert(!Deoptimization::reason_is_speculate(reason), "unsupported"); Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; if (treat_throw_as_hot - && (method()->method_data()->trap_recompiled_at(bci()) + && (method()->method_data()->trap_recompiled_at(bci(), NULL) || C->too_many_traps(reason))) { // We cannot afford to take more traps here. Suffer in the interpreter. if (C->log() != NULL) @@ -2145,7 +2146,7 @@ Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { * * @param n receiver node * - * @return node with improved type + * @return node with improved type */ Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) { if (!UseTypeSpeculation) { @@ -2739,12 +2740,14 @@ bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) { // Subsequent type checks will always fold up. Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, ciKlass* require_klass, - ciKlass* spec_klass, + ciKlass* spec_klass, bool safe_for_replace) { if (!UseTypeProfile || !TypeProfileCasts) return NULL; + Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check; + // Make sure we haven't already deoptimized from this tactic. - if (too_many_traps(Deoptimization::Reason_class_check)) + if (too_many_traps(reason)) return NULL; // (No, this isn't a call, but it's enough like a virtual call @@ -2766,7 +2769,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, &exact_obj); { PreserveJVMState pjvms(this); set_control(slow_ctl); - uncommon_trap(Deoptimization::Reason_class_check, + uncommon_trap(reason, Deoptimization::Action_maybe_recompile); } if (safe_for_replace) { @@ -2793,8 +2796,10 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj, bool not_null) { // type == NULL if profiling tells us this object is always null if (type != NULL) { - if (!too_many_traps(Deoptimization::Reason_null_check) && - !too_many_traps(Deoptimization::Reason_class_check)) { + Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; + Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; + if (!too_many_traps(null_reason) && + !too_many_traps(class_reason)) { Node* not_null_obj = NULL; // not_null is true if we know the object is not null and // there's no need for a null check @@ -2813,7 +2818,7 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj, { PreserveJVMState pjvms(this); set_control(slow_ctl); - uncommon_trap(Deoptimization::Reason_class_check, + uncommon_trap(class_reason, Deoptimization::Action_maybe_recompile); } replace_in_map(not_null_obj, exact_obj); @@ -2882,7 +2887,7 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac } if (known_statically && UseTypeSpeculation) { - // If we know the type check always succeed then we don't use the + // If we know the type check always succeeds then we don't use the // profiling data at this bytecode. Don't lose it, feed it to the // type system as a speculative type. not_null_obj = record_profiled_receiver_for_speculation(not_null_obj); diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index e49c4684686..fbbf8c9aa86 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -406,7 +406,7 @@ class GraphKit : public Phase { // Use the type profile to narrow an object type. Node* maybe_cast_profiled_receiver(Node* not_null_obj, ciKlass* require_klass, - ciKlass* spec, + ciKlass* spec, bool safe_for_replace); // Cast obj to type and emit guard unless we had too many traps here already diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 69b9e86c582..b1b078f6491 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1489,6 +1489,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra bool maybe_prior_trap = false; bool maybe_prior_recompile = false; pdata = query_update_method_data(trap_mdo, trap_bci, reason, + nm->method(), //outputs: this_trap_count, maybe_prior_trap, @@ -1534,7 +1535,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra } // Go back to the compiler if there are too many traps in this method. - if (this_trap_count >= (uint)PerMethodTrapLimit) { + if (this_trap_count >= per_method_trap_limit(reason)) { // If there are too many traps in this method, force a recompile. // This will allow the compiler to see the limit overflow, and // take corrective action, if possible. @@ -1622,6 +1623,7 @@ ProfileData* Deoptimization::query_update_method_data(MethodData* trap_mdo, int trap_bci, Deoptimization::DeoptReason reason, + Method* compiled_method, //outputs: uint& ret_this_trap_count, bool& ret_maybe_prior_trap, @@ -1645,9 +1647,16 @@ Deoptimization::query_update_method_data(MethodData* trap_mdo, // Find the profile data for this BCI. If there isn't one, // try to allocate one from the MDO's set of spares. // This will let us detect a repeated trap at this point. - pdata = trap_mdo->allocate_bci_to_data(trap_bci); + pdata = trap_mdo->allocate_bci_to_data(trap_bci, reason_is_speculate(reason) ? compiled_method : NULL); if (pdata != NULL) { + if (reason_is_speculate(reason) && !pdata->is_SpeculativeTrapData()) { + if (LogCompilation && xtty != NULL) { + ttyLocker ttyl; + // no more room for speculative traps in this MDO + xtty->elem("speculative_traps_oom"); + } + } // Query the trap state of this profile datum. int tstate0 = pdata->trap_state(); if (!trap_state_has_reason(tstate0, per_bc_reason)) @@ -1685,8 +1694,10 @@ Deoptimization::update_method_data_from_interpreter(MethodData* trap_mdo, int tr uint ignore_this_trap_count; bool ignore_maybe_prior_trap; bool ignore_maybe_prior_recompile; + assert(!reason_is_speculate(reason), "reason speculate only used by compiler"); query_update_method_data(trap_mdo, trap_bci, (DeoptReason)reason, + NULL, ignore_this_trap_count, ignore_maybe_prior_trap, ignore_maybe_prior_recompile); @@ -1814,7 +1825,8 @@ const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = { "div0_check", "age", "predicate", - "loop_limit_check" + "loop_limit_check", + "speculate_class_check" }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index a32e33ca928..f2233c9869b 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -59,6 +59,7 @@ class Deoptimization : AllStatic { Reason_age, // nmethod too old; tier threshold reached Reason_predicate, // compiler generated predicate failed Reason_loop_limit_check, // compiler generated loop limits check failed + Reason_speculate_class_check, // saw unexpected object class from type speculation Reason_LIMIT, // Note: Keep this enum in sync. with _trap_reason_name. Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc @@ -311,10 +312,23 @@ class Deoptimization : AllStatic { return reason; else if (reason == Reason_div0_check) // null check due to divide-by-zero? return Reason_null_check; // recorded per BCI as a null check + else if (reason == Reason_speculate_class_check) + return Reason_class_check; else return Reason_none; } + static bool reason_is_speculate(int reason) { + if (reason == Reason_speculate_class_check) { + return true; + } + return false; + } + + static uint per_method_trap_limit(int reason) { + return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit; + } + static const char* trap_reason_name(int reason); static const char* trap_action_name(int action); // Format like reason='foo' action='bar' index='123'. @@ -337,6 +351,7 @@ class Deoptimization : AllStatic { static ProfileData* query_update_method_data(MethodData* trap_mdo, int trap_bci, DeoptReason reason, + Method* compiled_method, //outputs: uint& ret_this_trap_count, bool& ret_maybe_prior_trap, diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index d9cd10f9c3c..b971907b980 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3078,9 +3078,15 @@ class CommandLineFlags { product(intx, PerMethodTrapLimit, 100, \ "Limit on traps (of one kind) in a method (includes inlines)") \ \ + experimental(intx, PerMethodSpecTrapLimit, 5000, \ + "Limit on speculative traps (of one kind) in a method (includes inlines)") \ + \ product(intx, PerBytecodeTrapLimit, 4, \ "Limit on traps (of one kind) at a particular BCI") \ \ + experimental(intx, SpecTrapLimitExtraEntries, 3, \ + "Extra method data trap entries for speculation") \ + \ develop(intx, InlineFrequencyRatio, 20, \ "Ratio of call site execution to caller method invocation") \ \ diff --git a/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java b/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java new file mode 100644 index 00000000000..11572672afe --- /dev/null +++ b/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031752 + * @summary speculative traps need to be cleaned up at GC + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading + * + */ + +import java.lang.reflect.Method; + +public class TestSpecTrapClassUnloading { + static class B { + final public boolean m(Object o) { + if (o.getClass() == B.class) { + return true; + } + return false; + } + } + + static class MemoryChunk { + MemoryChunk other; + long[] array; + MemoryChunk(MemoryChunk other) { + other = other; + array = new long[1024 * 1024 * 1024]; + } + } + + static void m1(B b, Object o) { + b.m(o); + } + + static void m2(B b, Object o) { + b.m(o); + } + + public static void main(String[] args) throws Exception { + Method m = B.class.getMethod("m", Object.class); + Object o = new Object(); + B b = new B(); + + // add speculative trap in B.m() for m1 + for (int i = 0; i < 20000; i++) { + m1(b, b); + } + m1(b, o); + + // add speculative trap in B.m() for code generated by reflection + for (int i = 0; i < 20000; i++) { + m.invoke(b, b); + } + m.invoke(b, o); + + m = null; + + // add speculative trap in B.m() for m2 + for (int i = 0; i < 20000; i++) { + m2(b, b); + } + m2(b, o); + + // Exhaust memory which causes the code generated by + // reflection to be unloaded but B.m() is not. + MemoryChunk root = null; + try { + while (true) { + root = new MemoryChunk(root); + } + } catch(OutOfMemoryError e) { + root = null; + } + } +} From 38cc4704111549e6f97cc95738cfbf89b1a56f12 Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Tue, 25 Feb 2014 14:06:48 -0500 Subject: [PATCH 195/265] 8035758: Move annotation codepaths from MemberEnter.java to Annotate.java Cosmetic code cleanup patch, moving code to the file where it ought to reside. Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Annotate.java | 291 +++++++++++++++++- .../com/sun/tools/javac/comp/Attr.java | 8 +- .../com/sun/tools/javac/comp/MemberEnter.java | 281 +---------------- 3 files changed, 295 insertions(+), 285 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index fe0b39a885b..cc0636ba257 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -25,8 +25,12 @@ package com.sun.tools.javac.comp; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; +import javax.tools.JavaFileObject; + import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.*; @@ -34,6 +38,7 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; +import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -57,15 +62,21 @@ public class Annotate { return instance; } - final Attr attr; - final TreeMaker make; - final Log log; - final Symtab syms; - final Names names; - final Resolve rs; - final Types types; - final ConstFold cfolder; - final Check chk; + private final Attr attr; + private final TreeMaker make; + private final Log log; + private final Symtab syms; + private final Names names; + private final Resolve rs; + private final Types types; + private final ConstFold cfolder; + private final Check chk; + private final Lint lint; + private final DeferredLintHandler deferredLintHandler; + private final Source source; + + private boolean allowTypeAnnos; + private boolean allowRepeatedAnnos; protected Annotate(Context context) { context.put(annotateKey, this); @@ -78,6 +89,11 @@ public class Annotate { types = Types.instance(context); cfolder = ConstFold.instance(context); chk = Check.instance(context); + source = Source.instance(context); + lint = Lint.instance(context); + deferredLintHandler = DeferredLintHandler.instance(context); + allowRepeatedAnnos = source.allowRepeatedAnnotations(); + allowTypeAnnos = source.allowTypeAnnotations(); } /* ******************************************************************** @@ -669,4 +685,261 @@ public class Annotate { return fatalError ? null : containerValueSymbol; } + +/* ******************************************************************** + * Annotation processing + *********************************************************************/ + + /** Queue annotations for later processing. */ + void annotateLater(final List annotations, + final Env localEnv, + final Symbol s, + final DiagnosticPosition deferPos) { + if (annotations.isEmpty()) { + return; + } + if (s.kind != PCK) { + s.resetAnnotations(); // mark Annotations as incomplete for now + } + normal(new Annotate.Worker() { + @Override + public String toString() { + return "annotate " + annotations + " onto " + s + " in " + s.owner; + } + + @Override + public void run() { + Assert.check(s.kind == PCK || s.annotationsPendingCompletion()); + JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); + DiagnosticPosition prevLintPos = + deferPos != null + ? deferredLintHandler.setPos(deferPos) + : deferredLintHandler.immediate(); + Lint prevLint = deferPos != null ? null : chk.setLint(lint); + try { + if (s.hasAnnotations() && + annotations.nonEmpty()) + log.error(annotations.head.pos, + "already.annotated", + kindName(s), s); + actualEnterAnnotations(annotations, localEnv, s); + } finally { + if (prevLint != null) + chk.setLint(prevLint); + deferredLintHandler.setPos(prevLintPos); + log.useSource(prev); + } + } + }); + + validate(new Annotate.Worker() { //validate annotations + @Override + public void run() { + JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); + try { + chk.validateAnnotations(annotations, s); + } finally { + log.useSource(prev); + } + } + }); + } + + /** Enter a set of annotations. */ + private void actualEnterAnnotations(List annotations, + Env env, + Symbol s) { + Map> annotated = new LinkedHashMap<>(); + Map pos = new HashMap<>(); + + for (List al = annotations; !al.isEmpty(); al = al.tail) { + JCAnnotation a = al.head; + Attribute.Compound c = enterAnnotation(a, syms.annotationType, env); + if (c == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (!allowRepeatedAnnos) { + log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); + allowRepeatedAnnos = true; + } + ListBuffer l = annotated.get(a.type.tsym); + l = l.append(c); + annotated.put(a.type.tsym, l); + pos.put(c, a.pos()); + } else { + annotated.put(a.type.tsym, ListBuffer.of(c)); + pos.put(c, a.pos()); + } + + // Note: @Deprecated has no effect on local variables and parameters + if (!c.type.isErroneous() + && s.owner.kind != MTH + && types.isSameType(c.type, syms.deprecatedType)) { + s.flags_field |= Flags.DEPRECATED; + } + } + + s.setDeclarationAttributesWithCompletion( + new AnnotateRepeatedContext<>(env, annotated, pos, log, false)); + } + + /* + * If the symbol is non-null, attach the type annotation to it. + */ + private void actualEnterTypeAnnotations(final List annotations, + final Env env, + final Symbol s) { + Map> annotated = new LinkedHashMap<>(); + Map pos = new HashMap<>(); + + for (List al = annotations; !al.isEmpty(); al = al.tail) { + JCAnnotation a = al.head; + Attribute.TypeCompound tc = + enterTypeAnnotation(a, syms.annotationType, env); + + if (tc == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (!allowRepeatedAnnos) { + log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); + allowRepeatedAnnos = true; + } + ListBuffer l = annotated.get(a.type.tsym); + l = l.append(tc); + annotated.put(a.type.tsym, l); + pos.put(tc, a.pos()); + } else { + annotated.put(a.type.tsym, ListBuffer.of(tc)); + pos.put(tc, a.pos()); + } + } + + if (s != null) { + s.appendTypeAttributesWithCompletion( + new AnnotateRepeatedContext<>(env, annotated, pos, log, true)); + } + } + + public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym, DiagnosticPosition deferPos) { + if (allowTypeAnnos) { + tree.accept(new TypeAnnotate(env, sym, deferPos)); + } + } + + /** + * We need to use a TreeScanner, because it is not enough to visit the top-level + * annotations. We also need to visit type arguments, etc. + */ + private class TypeAnnotate extends TreeScanner { + private Env env; + private Symbol sym; + private DiagnosticPosition deferPos; + + public TypeAnnotate(final Env env, final Symbol sym, DiagnosticPosition deferPos) { + this.env = env; + this.sym = sym; + this.deferPos = deferPos; + } + + void annotateTypeLater(final List annotations) { + if (annotations.isEmpty()) { + return; + } + + final DiagnosticPosition deferPos = this.deferPos; + + normal(new Annotate.Worker() { + @Override + public String toString() { + return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; + } + @Override + public void run() { + JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + DiagnosticPosition prevLintPos = null; + + if (deferPos != null) { + prevLintPos = deferredLintHandler.setPos(deferPos); + } + try { + actualEnterTypeAnnotations(annotations, env, sym); + } finally { + if (prevLintPos != null) + deferredLintHandler.setPos(prevLintPos); + log.useSource(prev); + } + } + }); + } + + @Override + public void visitAnnotatedType(final JCAnnotatedType tree) { + annotateTypeLater(tree.annotations); + super.visitAnnotatedType(tree); + } + + @Override + public void visitTypeParameter(final JCTypeParameter tree) { + annotateTypeLater(tree.annotations); + super.visitTypeParameter(tree); + } + + @Override + public void visitNewArray(final JCNewArray tree) { + annotateTypeLater(tree.annotations); + for (List dimAnnos : tree.dimAnnotations) + annotateTypeLater(dimAnnos); + super.visitNewArray(tree); + } + + @Override + public void visitMethodDef(final JCMethodDecl tree) { + scan(tree.mods); + scan(tree.restype); + scan(tree.typarams); + scan(tree.recvparam); + scan(tree.params); + scan(tree.thrown); + scan(tree.defaultValue); + // Do not annotate the body, just the signature. + // scan(tree.body); + } + + @Override + public void visitVarDef(final JCVariableDecl tree) { + DiagnosticPosition prevPos = deferPos; + deferPos = tree.pos(); + try { + if (sym != null && sym.kind == Kinds.VAR) { + // Don't visit a parameter once when the sym is the method + // and once when the sym is the parameter. + scan(tree.mods); + scan(tree.vartype); + } + scan(tree.init); + } finally { + deferPos = prevPos; + } + } + + @Override + public void visitClassDef(JCClassDecl tree) { + // We can only hit a classdef if it is declared within + // a method. Ignore it - the class will be visited + // separately later. + } + + @Override + public void visitNewClass(JCNewClass tree) { + if (tree.def == null) { + // For an anonymous class instantiation the class + // will be visited separately. + super.visitNewClass(tree); + } + } + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index d8841c3be78..7f0cded8001 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -774,7 +774,7 @@ public class Attr extends JCTree.Visitor { // to the symbol. // This prevents having multiple type annotations, just because of // lazy constant value evaluation. - memberEnter.typeAnnotate(variable.init, env, null, variable.pos()); + annotate.typeAnnotate(variable.init, env, null, variable.pos()); annotate.flush(); Type itype = attribExpr(variable.init, env, type); if (itype.constValue() != null) { @@ -1021,7 +1021,7 @@ public class Attr extends JCTree.Visitor { } // Attribute all type annotations in the body - memberEnter.typeAnnotate(tree.body, localEnv, m, null); + annotate.typeAnnotate(tree.body, localEnv, m, null); annotate.flush(); // Attribute method body. @@ -1050,7 +1050,7 @@ public class Attr extends JCTree.Visitor { } else { if (tree.init != null) { // Field initializer expression need to be entered. - memberEnter.typeAnnotate(tree.init, env, tree.sym, tree.pos()); + annotate.typeAnnotate(tree.init, env, tree.sym, tree.pos()); annotate.flush(); } } @@ -1111,7 +1111,7 @@ public class Attr extends JCTree.Visitor { if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; // Attribute all type annotations in the block - memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); + annotate.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); annotate.flush(); { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 8db141167ea..03ac3c42a3f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -113,15 +113,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { deferredLintHandler = DeferredLintHandler.instance(context); lint = Lint.instance(context); allowTypeAnnos = source.allowTypeAnnotations(); - allowRepeatedAnnos = source.allowRepeatedAnnotations(); } /** Switch: support type annotations. */ boolean allowTypeAnnos; - boolean allowRepeatedAnnos; - /** A queue for classes whose members still need to be entered into the * symbol table. */ @@ -512,7 +509,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } // process package annotations - annotateLater(tree.packageAnnotations, env, tree.packge, null); + annotate.annotateLater(tree.packageAnnotations, env, tree.packge, null); DiagnosticPosition prevLintPos = deferredLintHandler.immediate(); Lint prevLint = chk.setLint(lint); @@ -607,10 +604,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(m); } - annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); + annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); // Visit the signature of the method. Note that // TypeAnnotate doesn't descend into the body. - typeAnnotate(tree, localEnv, m, tree.pos()); + annotate.typeAnnotate(tree, localEnv, m, tree.pos()); if (tree.defaultValue != null) annotateDefaultValueLater(tree.defaultValue, localEnv, m); @@ -700,8 +697,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { chk.checkTransparentVar(tree.pos(), v, enclScope); enclScope.enter(v); } - annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); - typeAnnotate(tree.vartype, env, v, tree.pos()); + annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); + annotate.typeAnnotate(tree.vartype, env, v, tree.pos()); v.pos = tree.pos; } finally { annotate.enterDone(); @@ -838,65 +835,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } -/* ******************************************************************** - * Annotation processing - *********************************************************************/ - - /** Queue annotations for later processing. */ - void annotateLater(final List annotations, - final Env localEnv, - final Symbol s, - final DiagnosticPosition deferPos) { - if (annotations.isEmpty()) { - return; - } - if (s.kind != PCK) { - s.resetAnnotations(); // mark Annotations as incomplete for now - } - annotate.normal(new Annotate.Worker() { - @Override - public String toString() { - return "annotate " + annotations + " onto " + s + " in " + s.owner; - } - - @Override - public void run() { - Assert.check(s.kind == PCK || s.annotationsPendingCompletion()); - JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); - DiagnosticPosition prevLintPos = - deferPos != null - ? deferredLintHandler.setPos(deferPos) - : deferredLintHandler.immediate(); - Lint prevLint = deferPos != null ? null : chk.setLint(lint); - try { - if (s.hasAnnotations() && - annotations.nonEmpty()) - log.error(annotations.head.pos, - "already.annotated", - kindName(s), s); - actualEnterAnnotations(annotations, localEnv, s); - } finally { - if (prevLint != null) - chk.setLint(prevLint); - deferredLintHandler.setPos(prevLintPos); - log.useSource(prev); - } - } - }); - - annotate.validate(new Annotate.Worker() { //validate annotations - @Override - public void run() { - JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); - try { - chk.validateAnnotations(annotations, s); - } finally { - log.useSource(prev); - } - } - }); - } - /** * Check if a list of annotations contains a reference to * java.lang.Deprecated. @@ -910,48 +848,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { return false; } - /** Enter a set of annotations. */ - private void actualEnterAnnotations(List annotations, - Env env, - Symbol s) { - Map> annotated = new LinkedHashMap<>(); - Map pos = new HashMap<>(); - - for (List al = annotations; !al.isEmpty(); al = al.tail) { - JCAnnotation a = al.head; - Attribute.Compound c = annotate.enterAnnotation(a, - syms.annotationType, - env); - if (c == null) { - continue; - } - - if (annotated.containsKey(a.type.tsym)) { - if (!allowRepeatedAnnos) { - log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); - allowRepeatedAnnos = true; - } - ListBuffer l = annotated.get(a.type.tsym); - l = l.append(c); - annotated.put(a.type.tsym, l); - pos.put(c, a.pos()); - } else { - annotated.put(a.type.tsym, ListBuffer.of(c)); - pos.put(c, a.pos()); - } - - // Note: @Deprecated has no effect on local variables and parameters - if (!c.type.isErroneous() - && s.owner.kind != MTH - && types.isSameType(c.type, syms.deprecatedType)) { - s.flags_field |= Flags.DEPRECATED; - } - } - - s.setDeclarationAttributesWithCompletion( - annotate.new AnnotateRepeatedContext<>(env, annotated, pos, log, false)); - } - /** Queue processing of an attribute default value. */ void annotateDefaultValueLater(final JCExpression defaultValue, final Env localEnv, @@ -1043,9 +939,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { Env baseEnv = baseEnv(tree, env); if (tree.extending != null) - typeAnnotate(tree.extending, baseEnv, sym, tree.pos()); + annotate.typeAnnotate(tree.extending, baseEnv, sym, tree.pos()); for (JCExpression impl : tree.implementing) - typeAnnotate(impl, baseEnv, sym, tree.pos()); + annotate.typeAnnotate(impl, baseEnv, sym, tree.pos()); annotate.flush(); // Determine supertype. @@ -1106,7 +1002,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); if (hasDeprecatedAnnotation(tree.mods.annotations)) c.flags_field |= DEPRECATED; - annotateLater(tree.mods.annotations, baseEnv, c, tree.pos()); + annotate.annotateLater(tree.mods.annotations, baseEnv, c, tree.pos()); // class type parameters use baseEnv but everything uses env chk.checkNonCyclicDecl(tree); @@ -1114,7 +1010,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribTypeVariables(tree.typarams, baseEnv); // Do this here, where we have the symbol. for (JCTypeParameter tp : tree.typarams) - typeAnnotate(tp, baseEnv, sym, tree.pos()); + annotate.typeAnnotate(tp, baseEnv, sym, tree.pos()); // Add default constructor if needed. if ((c.flags() & INTERFACE) == 0 && @@ -1205,165 +1101,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } - /* - * If the symbol is non-null, attach the type annotation to it. - */ - private void actualEnterTypeAnnotations(final List annotations, - final Env env, - final Symbol s) { - Map> annotated = new LinkedHashMap<>(); - Map pos = new HashMap<>(); - - for (List al = annotations; !al.isEmpty(); al = al.tail) { - JCAnnotation a = al.head; - Attribute.TypeCompound tc = annotate.enterTypeAnnotation(a, - syms.annotationType, - env); - if (tc == null) { - continue; - } - - if (annotated.containsKey(a.type.tsym)) { - if (source.allowRepeatedAnnotations()) { - ListBuffer l = annotated.get(a.type.tsym); - l = l.append(tc); - annotated.put(a.type.tsym, l); - pos.put(tc, a.pos()); - } else { - log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); - } - } else { - annotated.put(a.type.tsym, ListBuffer.of(tc)); - pos.put(tc, a.pos()); - } - } - - if (s != null) { - s.appendTypeAttributesWithCompletion( - annotate.new AnnotateRepeatedContext<>(env, annotated, pos, log, true)); - } - } - - public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym, DiagnosticPosition deferPos) { - if (allowTypeAnnos) { - tree.accept(new TypeAnnotate(env, sym, deferPos)); - } - } - - /** - * We need to use a TreeScanner, because it is not enough to visit the top-level - * annotations. We also need to visit type arguments, etc. - */ - private class TypeAnnotate extends TreeScanner { - private Env env; - private Symbol sym; - private DiagnosticPosition deferPos; - - public TypeAnnotate(final Env env, final Symbol sym, DiagnosticPosition deferPos) { - this.env = env; - this.sym = sym; - this.deferPos = deferPos; - } - - void annotateTypeLater(final List annotations) { - if (annotations.isEmpty()) { - return; - } - - final DiagnosticPosition deferPos = this.deferPos; - - annotate.normal(new Annotate.Worker() { - @Override - public String toString() { - return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; - } - @Override - public void run() { - JavaFileObject prev = log.useSource(env.toplevel.sourcefile); - DiagnosticPosition prevLintPos = null; - - if (deferPos != null) { - prevLintPos = deferredLintHandler.setPos(deferPos); - } - try { - actualEnterTypeAnnotations(annotations, env, sym); - } finally { - if (prevLintPos != null) - deferredLintHandler.setPos(prevLintPos); - log.useSource(prev); - } - } - }); - } - - @Override - public void visitAnnotatedType(final JCAnnotatedType tree) { - annotateTypeLater(tree.annotations); - super.visitAnnotatedType(tree); - } - - @Override - public void visitTypeParameter(final JCTypeParameter tree) { - annotateTypeLater(tree.annotations); - super.visitTypeParameter(tree); - } - - @Override - public void visitNewArray(final JCNewArray tree) { - annotateTypeLater(tree.annotations); - for (List dimAnnos : tree.dimAnnotations) - annotateTypeLater(dimAnnos); - super.visitNewArray(tree); - } - - @Override - public void visitMethodDef(final JCMethodDecl tree) { - scan(tree.mods); - scan(tree.restype); - scan(tree.typarams); - scan(tree.recvparam); - scan(tree.params); - scan(tree.thrown); - scan(tree.defaultValue); - // Do not annotate the body, just the signature. - // scan(tree.body); - } - - @Override - public void visitVarDef(final JCVariableDecl tree) { - DiagnosticPosition prevPos = deferPos; - deferPos = tree.pos(); - try { - if (sym != null && sym.kind == Kinds.VAR) { - // Don't visit a parameter once when the sym is the method - // and once when the sym is the parameter. - scan(tree.mods); - scan(tree.vartype); - } - scan(tree.init); - } finally { - deferPos = prevPos; - } - } - - @Override - public void visitClassDef(JCClassDecl tree) { - // We can only hit a classdef if it is declared within - // a method. Ignore it - the class will be visited - // separately later. - } - - @Override - public void visitNewClass(JCNewClass tree) { - if (tree.def == null) { - // For an anonymous class instantiation the class - // will be visited separately. - super.visitNewClass(tree); - } - } - } - - private Env baseEnv(JCClassDecl tree, Env env) { Scope baseScope = new Scope(tree.sym); //import already entered local classes into base scope From 39b5a040cd0ba9af055e48257ae00af3d1d0c5cb Mon Sep 17 00:00:00 2001 From: Albert Noll Date: Wed, 26 Feb 2014 07:44:59 +0100 Subject: [PATCH 196/265] 8032642: [TESTBUG] Fix testbugs in compiler/startup/.* Fixed issues with these tests Reviewed-by: kvn, twisti --- .../compiler/startup/SmallCodeCacheStartup.java | 16 +++++----------- hotspot/test/compiler/startup/StartupOutput.java | 3 +-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/hotspot/test/compiler/startup/SmallCodeCacheStartup.java b/hotspot/test/compiler/startup/SmallCodeCacheStartup.java index 7a9a11a0836..5db43673fa8 100644 --- a/hotspot/test/compiler/startup/SmallCodeCacheStartup.java +++ b/hotspot/test/compiler/startup/SmallCodeCacheStartup.java @@ -24,19 +24,13 @@ /* * @test * @bug 8023014 - * @summary Test ensures that there is no crash when compiler initialization fails - * @library /testlibrary - * + * @summary Test ensures that there is no crash if there is not enough ReservedCodeacacheSize + * to initialize all compiler threads. The option -Xcomp gives the VM more time to + * to trigger the old bug. + * @run main/othervm -XX:ReservedCodeCacheSize=3m -XX:CICompilerCount=64 -Xcomp SmallCodeCacheStartup */ -import com.oracle.java.testlibrary.*; - public class SmallCodeCacheStartup { public static void main(String[] args) throws Exception { - ProcessBuilder pb; - OutputAnalyzer out; - - pb = ProcessTools.createJavaProcessBuilder("-XX:ReservedCodeCacheSize=3m", "-XX:CICompilerCount=64", "-version"); - out = new OutputAnalyzer(pb.start()); - out.shouldHaveExitValue(0); + System.out.println("TEST PASSED"); } } diff --git a/hotspot/test/compiler/startup/StartupOutput.java b/hotspot/test/compiler/startup/StartupOutput.java index f677853d51c..e4a1b4cd4c5 100644 --- a/hotspot/test/compiler/startup/StartupOutput.java +++ b/hotspot/test/compiler/startup/StartupOutput.java @@ -25,8 +25,7 @@ * @test * @bug 8026949 * @summary Test ensures correct VM output during startup - * @library ../../testlibrary - * + * @library /testlibrary */ import com.oracle.java.testlibrary.*; From 94a86285a7a3d61a4b278ad11b5bea7c28b94609 Mon Sep 17 00:00:00 2001 From: Niclas Adlertz Date: Wed, 26 Feb 2014 07:46:46 +0100 Subject: [PATCH 197/265] 8010500: [parfait] Possible null pointer dereference at hotspot/src/share/vm/opto/loopnode.hpp Added NULL check for loopnode() in get_pre_loop_end() Reviewed-by: kvn, roland --- hotspot/src/share/vm/opto/superword.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp index 96c81bd999c..9363caa1da4 100644 --- a/hotspot/src/share/vm/opto/superword.cpp +++ b/hotspot/src/share/vm/opto/superword.cpp @@ -441,6 +441,7 @@ bool SuperWord::ref_is_alignable(SWPointer& p) { return true; // no induction variable } CountedLoopEndNode* pre_end = get_pre_loop_end(lp()->as_CountedLoop()); + assert(pre_end != NULL, "we must have a correct pre-loop"); assert(pre_end->stride_is_con(), "pre loop stride is constant"); int preloop_stride = pre_end->stride_con(); @@ -1981,7 +1982,7 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) { CountedLoopNode *main_head = lp()->as_CountedLoop(); assert(main_head->is_main_loop(), ""); CountedLoopEndNode* pre_end = get_pre_loop_end(main_head); - assert(pre_end != NULL, ""); + assert(pre_end != NULL, "we must have a correct pre-loop"); Node *pre_opaq1 = pre_end->limit(); assert(pre_opaq1->Opcode() == Op_Opaque1, ""); Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1; @@ -2145,7 +2146,8 @@ CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode *cl) { if (!p_f->is_IfFalse()) return NULL; if (!p_f->in(0)->is_CountedLoopEnd()) return NULL; CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); - if (!pre_end->loopnode()->is_pre_loop()) return NULL; + CountedLoopNode* loop_node = pre_end->loopnode(); + if (loop_node == NULL || !loop_node->is_pre_loop()) return NULL; return pre_end; } From ac4f26242b49e6d31dbc7a854540e73a8cae5ab3 Mon Sep 17 00:00:00 2001 From: Henry Jen Date: Tue, 25 Feb 2014 23:59:04 -0800 Subject: [PATCH 198/265] 8033898: undefined symbol when build hotspot with Xcode5 Reviewed-by: sla, dholmes --- hotspot/make/bsd/makefiles/gcc.make | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index b6bca43e5bd..9c9cef07f82 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -364,6 +364,11 @@ ASFLAGS += -x assembler-with-cpp # statically link libstdc++.so, work with gcc but ignored by g++ STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic +# Ensure use libstdc++ on clang, not libc++ +ifeq ($(USE_CLANG), true) + LFLAGS += -stdlib=libstdc++ +endif + ifeq ($(USE_CLANG),) # statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x. ifneq ("${CC_VER_MAJOR}", "2") From aa570e227cd673291806ec48c53472c34e271be7 Mon Sep 17 00:00:00 2001 From: Albert Noll Date: Wed, 26 Feb 2014 11:29:47 +0100 Subject: [PATCH 199/265] 8034839: jvm hangs with gc/gctests/LoadUnloadGC test Provide fast lookup of checked dependencies via hashmap Reviewed-by: kvn, roland --- hotspot/src/share/vm/code/codeCache.cpp | 5 +- hotspot/src/share/vm/code/dependencies.cpp | 45 +------ hotspot/src/share/vm/code/dependencies.hpp | 15 +-- hotspot/src/share/vm/code/nmethod.cpp | 14 +-- hotspot/src/share/vm/utilities/hashtable.cpp | 116 ++++++++++++++++++- hotspot/src/share/vm/utilities/hashtable.hpp | 84 +++++++++++++- 6 files changed, 212 insertions(+), 67 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 5e9b343cd2b..3d7758304a8 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -595,11 +595,8 @@ void CodeCache::clear_inline_caches() { } } -#ifndef PRODUCT // Keeps track of time spent for checking dependencies -static elapsedTimer dependentCheckTime; -#endif - +NOT_PRODUCT(static elapsedTimer dependentCheckTime;) int CodeCache::mark_for_deoptimization(DepChange& changes) { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp index 5363aed99c5..d3dcf5da9a6 100644 --- a/hotspot/src/share/vm/code/dependencies.cpp +++ b/hotspot/src/share/vm/code/dependencies.cpp @@ -725,56 +725,19 @@ Klass* Dependencies::DepStream::context_type() { } // ----------------- DependencySignature -------------------------------------- -bool DependencySignature::equals(const DependencySignature& sig) const { - if (type() != sig.type()) { +bool DependencySignature::equals(DependencySignature* sig) const { + if ((type() != sig->type()) || (args_count() != sig->args_count())) { return false; } - if (args_count() != sig.args_count()) { - return false; - } - - for (int i = 0; i < sig.args_count(); i++) { - if (arg(i) != sig.arg(i)) { + for (int i = 0; i < sig->args_count(); i++) { + if (arg(i) != sig->arg(i)) { return false; } } return true; } - -// ----------------- DependencySignatureBuffer -------------------------------------- -DependencySignatureBuffer::DependencySignatureBuffer() { - _signatures = NEW_RESOURCE_ARRAY(GrowableArray*, Dependencies::TYPE_LIMIT); - memset(_signatures, 0, sizeof(DependencySignature*) * Dependencies::TYPE_LIMIT); -} - -/* Check if arguments are identical. Two dependency signatures are considered - * identical, if the type as well as all argument identifiers are identical. - * If the dependency has not already been checked, the dependency signature is - * added to the checked dependencies of the same type. The function returns - * false, which causes the dependency to be checked in the caller. - */ -bool DependencySignatureBuffer::add_if_missing(const DependencySignature& sig) { - const int index = sig.type(); - GrowableArray* buffer = _signatures[index]; - if (buffer == NULL) { - buffer = new GrowableArray(); - _signatures[index] = buffer; - } - - // Check if we have already checked the dependency - for (int i = 0; i < buffer->length(); i++) { - DependencySignature* checked_signature = buffer->at(i); - if (checked_signature->equals(sig)) { - return true; - } - } - buffer->append((DependencySignature*)&sig); - return false; -} - - /// Checking dependencies: // This hierarchy walker inspects subtypes of a given type, diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp index 5b5d467b238..050478cbc85 100644 --- a/hotspot/src/share/vm/code/dependencies.hpp +++ b/hotspot/src/share/vm/code/dependencies.hpp @@ -32,6 +32,7 @@ #include "code/compressedStream.hpp" #include "code/nmethod.hpp" #include "utilities/growableArray.hpp" +#include "utilities/hashtable.hpp" //** Dependencies represent assertions (approximate invariants) within // the runtime system, e.g. class hierarchy changes. An example is an @@ -526,13 +527,12 @@ class Dependencies: public ResourceObj { }; -class DependencySignature : public ResourceObj { +class DependencySignature : public GenericHashtableEntry { private: int _args_count; uintptr_t _argument_hash[Dependencies::max_arg_count]; Dependencies::DepType _type; - public: DependencySignature(Dependencies::DepStream& dep) { _args_count = dep.argument_count(); @@ -542,21 +542,14 @@ class DependencySignature : public ResourceObj { } } - bool equals(const DependencySignature& sig) const; + bool equals(DependencySignature* sig) const; + uintptr_t key() const { return _argument_hash[0] >> 2; } int args_count() const { return _args_count; } uintptr_t arg(int idx) const { return _argument_hash[idx]; } Dependencies::DepType type() const { return _type; } }; -class DependencySignatureBuffer : public StackObj { - private: - GrowableArray** _signatures; - - public: - DependencySignatureBuffer(); - bool add_if_missing(const DependencySignature& sig); -}; // Every particular DepChange is a sub-class of this class. class DepChange : public StackObj { diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 4c4e56972ab..f4dd4aaa5eb 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -2168,25 +2168,21 @@ void nmethod::check_all_dependencies(DepChange& changes) { // Turn off dependency tracing while actually testing dependencies. NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) ); - // 'dep_signature_buffers' caches already checked dependencies. - DependencySignatureBuffer dep_signature_buffers; - + GenericHashtable* table = new GenericHashtable(11027); // Iterate over live nmethods and check dependencies of all nmethods that are not // marked for deoptimization. A particular dependency is only checked once. for(nmethod* nm = CodeCache::alive_nmethod(CodeCache::first()); nm != NULL; nm = CodeCache::alive_nmethod(CodeCache::next(nm))) { if (!nm->is_marked_for_deoptimization()) { for (Dependencies::DepStream deps(nm); deps.next(); ) { // Construct abstraction of a dependency. - const DependencySignature* current_sig = new DependencySignature(deps); - // Determine if 'deps' is already checked. If it is not checked, - // 'add_if_missing()' adds the dependency signature and returns - // false. - if (!dep_signature_buffers.add_if_missing(*current_sig)) { + DependencySignature* current_sig = new DependencySignature(deps); + // Determine if 'deps' is already checked. table->add() returns + // 'true' if the dependency was added (i.e., was not in the hashtable). + if (table->add(current_sig)) { if (deps.check_dependency() != NULL) { // Dependency checking failed. Print out information about the failed // dependency and finally fail with an assert. We can fail here, since // dependency checking is never done in a product build. - ResourceMark rm; changes.print(); nm->print(); nm->print_dependencies(); diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp index 40fb3b1537d..a850ebe87f4 100644 --- a/hotspot/src/share/vm/utilities/hashtable.cpp +++ b/hotspot/src/share/vm/utilities/hashtable.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/altHashing.hpp" #include "classfile/javaClasses.hpp" +#include "code/dependencies.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/resourceArea.hpp" @@ -338,7 +339,6 @@ template void BasicHashtable::verify() { #endif // PRODUCT - #ifdef ASSERT template void BasicHashtable::verify_lookup_length(double load) { @@ -351,6 +351,118 @@ template void BasicHashtable::verify_lookup_length(double load) } #endif + + +template GenericHashtable::GenericHashtable(int size, bool C_heap, MEMFLAGS memflag) { + assert(size > 0, " Invalid hashtable size"); + _size = size; + _C_heap = C_heap; + _memflag = memflag; + // Perform subtype-specific resource allocation + _items = (C_heap) ? NEW_C_HEAP_ARRAY(T*, size, memflag) : NEW_RESOURCE_ARRAY(T*, size); + memset(_items, 0, sizeof(T*) * size); + + DEBUG_ONLY(_num_items = 0;) +} + +template GenericHashtable::~GenericHashtable() { + if (on_C_heap()) { + // Check backing array + for (int i = 0; i < size(); i++) { + T* item = head(i); + // Delete all items in linked list + while (item != NULL) { + T* next_item = item->next(); + delete item; + DEBUG_ONLY(_num_items--); + item = next_item; + } + } + FREE_C_HEAP_ARRAY(T*, _items, _memflag); + _items = NULL; + assert (_num_items == 0, "Not all memory released"); + } +} + +/** + * Return a pointer to the item 'I' that is stored in the hashtable for + * which match_item->equals(I) == true. If no such item is found, NULL + * is returned. + */ +template T* GenericHashtable::contains(T* match_item) { + if (match_item != NULL) { + int idx = index(match_item); + return contains_impl(match_item, idx); + } + return NULL; +} + +/** + * Add item to the hashtable. Return 'true' if the item was added + * and false otherwise. + */ +template bool GenericHashtable::add(T* item) { + if (item != NULL) { + int idx = index(item); + T* found_item = contains_impl(item, idx); + if (found_item == NULL) { + T* list_head = head(idx); + item->set_next(list_head); + item->set_prev(NULL); + + if (list_head != NULL) { + list_head->set_prev(item); + } + set_head(item, idx); + DEBUG_ONLY(_num_items++); + return true; + } + } + return false; +} + +/** + * Removes an item 'I' from the hashtable, if present. 'I' is removed, if + * match_item->equals(I) == true. Removing an item from the hashtable does + * not free memory. + */ +template T* GenericHashtable::remove(T* match_item) { + if (match_item != NULL) { + int idx = index(match_item); + T* found_item = contains_impl(match_item, idx); + if (found_item != NULL) { + // Remove item from linked list + T* prev = found_item->prev(); + T* next = found_item->next(); + if (prev != NULL) { + prev->set_next(next); + } else { + set_head(next, idx); + } + if (next != NULL) { + next->set_prev(prev); + } + + DEBUG_ONLY(_num_items--); + return found_item; + } + } + return NULL; +} + + +template T* GenericHashtable::contains_impl(T* item, int idx) { + T* current_item = head(idx); + while (current_item != NULL) { + if (current_item->equals(item)) { + return current_item; + } + current_item = current_item->next(); + } + return NULL; +} + + // Explicitly instantiate these types template class Hashtable; template class Hashtable; @@ -370,3 +482,5 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; + +template class GenericHashtable; diff --git a/hotspot/src/share/vm/utilities/hashtable.hpp b/hotspot/src/share/vm/utilities/hashtable.hpp index aa45100249c..8294eaab3d2 100644 --- a/hotspot/src/share/vm/utilities/hashtable.hpp +++ b/hotspot/src/share/vm/utilities/hashtable.hpp @@ -300,7 +300,7 @@ public: }; -// Verions of hashtable where two handles are used to compute the index. +// Versions of hashtable where two handles are used to compute the index. template class TwoOopHashtable : public Hashtable { friend class VMStructs; @@ -327,4 +327,86 @@ public: } }; + +/* + * Usage of GenericHashtable: + * + * class X : public GenericHashtableEntry { + * + * // Implement virtual functions in class X + * bool equals(X* sig) const; + * uintptr_t hash() const; + * }; + * + * void foo() { + * GenericHashtable* table = new GenericHashtable(11027, false); + * + * X* elem = new X(); + * table->add(elem); + * table->contains(elem); + * } + * + * You can choose other allocation types as well. For example, to store the hashtable to a + * particular region (CHeapObj) simply replace ResourceObj with the desired type: + * + * class X : public GenericHashtableEntry > { ... }; + * + * To make the destructor (and remove) of the hashtable work: + * 1) override the delete operator of X + * 2) provide a destructor of the X + * + * You may also find it convenient to override the new operator. + * + * If you use this templates do not forget to add an explicit initialization + * (at the end of hashtable.cpp). + * + * template class GenericHashtable; + */ +template class GenericHashtableEntry : public M { + private: + T* _next; + T* _prev; + public: + // Must be implemented by subclass. + virtual uintptr_t key() const = 0; + virtual bool equals(T* other) const = 0; + + T* next() const { return _next; } + T* prev() const { return _prev; } + void set_next(T* item) { _next = item; } + void set_prev(T* item) { _prev = item; } + + // Constructor and destructor + GenericHashtableEntry() : _next(NULL), _prev(NULL) { }; + virtual ~GenericHashtableEntry() {}; +}; + +template class GenericHashtable : public M { + private: + T** _items; + int _size; + bool _C_heap; + MEMFLAGS _memflag; + + // Accessor methods + T* head (int idx) const { return _items[idx]; } + void set_head(T* item, int idx) { _items[idx] = item; } + int index (T* item) { assert(item != NULL, "missing null check"); return item->key() % size(); } + + // Helper function + T* contains_impl(T* item, int idx); + + DEBUG_ONLY(int _num_items;) + public: + GenericHashtable(int size, bool C_heap = false, MEMFLAGS memflag = mtNone); + ~GenericHashtable(); + T* contains(T* match_item); + T* remove (T* match_item); + bool add (T* item); + + + bool on_C_heap() const { return _C_heap; } + int size() const { return _size; } +}; + #endif // SHARE_VM_UTILITIES_HASHTABLE_HPP From ead6152f73d70414f7b1dbac86bee78a1c360643 Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Wed, 26 Feb 2014 14:52:42 +0100 Subject: [PATCH 200/265] 8035822: Unable to test minimalVM Moved the test code inside INCLUDE_ALL_GCS Reviewed-by: dholmes, stefank --- hotspot/src/share/vm/prims/jni.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 030393cd275..19b20537ae6 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3876,9 +3876,9 @@ void TestVirtualSpace_test(); void TestMetaspaceAux_test(); void TestMetachunk_test(); void TestVirtualSpaceNode_test(); -void TestOldFreeSpaceCalculation_test(); void TestNewSize_test(); #if INCLUDE_ALL_GCS +void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); void TestBufferingOopClosure_test(); #endif @@ -3899,12 +3899,12 @@ void execute_internal_vm_tests() { run_unit_test(QuickSort::test_quick_sort()); run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); - run_unit_test(TestOldFreeSpaceCalculation_test()); run_unit_test(TestNewSize_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif #if INCLUDE_ALL_GCS + run_unit_test(TestOldFreeSpaceCalculation_test()); run_unit_test(TestG1BiasedArray_test()); run_unit_test(HeapRegionRemSet::test_prt()); run_unit_test(TestBufferingOopClosure_test()); From c01a8b92632d827a4100a49f4dda0a8504211516 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 26 Feb 2014 11:33:34 -0800 Subject: [PATCH 201/265] 8035396: Introduce accessor for tmp_oop in frame Avoid #ifs by introducing the accessor function interpreter_frame_temp_oop_addr(). Reviewed-by: kvn, twisti --- hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp | 4 ++++ hotspot/src/cpu/x86/vm/frame_x86.inline.hpp | 4 ++++ hotspot/src/share/vm/runtime/frame.cpp | 15 ++------------- hotspot/src/share/vm/runtime/frame.hpp | 6 +++--- hotspot/src/share/vm/runtime/frame.inline.hpp | 7 +++++++ 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp index 61ef794abd0..b87681750d2 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp @@ -237,6 +237,10 @@ inline ConstantPoolCache** frame::interpreter_frame_cpoolcache_addr() const { inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const { return (ConstantPoolCache**)sp_addr_at( LcpoolCache->sp_offset_in_saved_window()); } + +inline oop* frame::interpreter_frame_temp_oop_addr() const { + return (oop *)(fp() + interpreter_frame_oop_temp_offset); +} #endif // CC_INTERP diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index bb161c9d4ea..9b875b83499 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -247,6 +247,10 @@ inline intptr_t* frame::interpreter_frame_tos_address() const { } } +inline oop* frame::interpreter_frame_temp_oop_addr() const { + return (oop *)(fp() + interpreter_frame_oop_temp_offset); +} + #endif /* CC_INTERP */ inline int frame::pd_oop_map_offset_adjustment() const { diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index f7cbf083838..7a44fe4fa2e 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -933,20 +933,9 @@ void frame::oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f, cld_f->do_cld(m->method_holder()->class_loader_data()); } -#if !defined(PPC32) || defined(ZERO) - if (m->is_native()) { -#ifdef CC_INTERP - interpreterState istate = get_interpreterState(); - f->do_oop((oop*)&istate->_oop_temp); -#else - f->do_oop((oop*)( fp() + interpreter_frame_oop_temp_offset )); -#endif /* CC_INTERP */ + if (m->is_native() PPC32_ONLY(&& m->is_static())) { + f->do_oop(interpreter_frame_temp_oop_addr()); } -#else // PPC32 - if (m->is_native() && m->is_static()) { - f->do_oop(interpreter_frame_mirror_addr()); - } -#endif // PPC32 int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals(); diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index f58638e05ad..ef515fb30e1 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -314,6 +314,9 @@ class frame VALUE_OBJ_CLASS_SPEC { void interpreter_frame_set_monitor_end(BasicObjectLock* value); #endif // CC_INTERP + // Address of the temp oop in the frame. Needed as GC root. + oop* interpreter_frame_temp_oop_addr() const; + // BasicObjectLocks: // // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end @@ -350,9 +353,6 @@ class frame VALUE_OBJ_CLASS_SPEC { void interpreter_frame_set_method(Method* method); Method** interpreter_frame_method_addr() const; ConstantPoolCache** interpreter_frame_cache_addr() const; -#ifdef PPC32 - oop* interpreter_frame_mirror_addr() const; -#endif public: // Entry frames diff --git a/hotspot/src/share/vm/runtime/frame.inline.hpp b/hotspot/src/share/vm/runtime/frame.inline.hpp index e00d2cf9d09..ce725956dee 100644 --- a/hotspot/src/share/vm/runtime/frame.inline.hpp +++ b/hotspot/src/share/vm/runtime/frame.inline.hpp @@ -87,6 +87,13 @@ inline bool frame::is_first_frame() const { return is_entry_frame() && entry_frame_is_first(); } +#ifdef CC_INTERP +inline oop* frame::interpreter_frame_temp_oop_addr() const { + interpreterState istate = get_interpreterState(); + return (oop *)&istate->_oop_temp; +} +#endif // CC_INTERP + // here are the platform-dependent bodies: #ifdef TARGET_ARCH_x86 From f6250d778417c055c75b5754b3c31bb657d3f621 Mon Sep 17 00:00:00 2001 From: Paul Govereau Date: Wed, 26 Feb 2014 15:38:55 -0800 Subject: [PATCH 202/265] 8034048: javac crash with method references plus lambda plus var args Reviewed-by: jjg, vromero --- .../share/classes/com/sun/tools/javac/comp/TransTypes.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 0d043ba1f61..9c30d1b9834 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -834,6 +834,8 @@ public class TransTypes extends TreeTranslator { public void visitReference(JCMemberReference tree) { tree.expr = translate(tree.expr, erasure(tree.expr.type)); tree.type = erasure(tree.type); + if (tree.varargsElement != null) + tree.varargsElement = erasure(tree.varargsElement); result = tree; } From 2c99a4ef9f12f5722625b4423a95e4042c7883ee Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 26 Feb 2014 16:45:15 -0800 Subject: [PATCH 203/265] 8035283: Second phase of branch shortening doesn't account for loop alignment Added missing check for loop padding case. Reviewed-by: kvn, jrose --- hotspot/src/share/vm/opto/output.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 1e6fbaadfe4..48117ea14fe 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -344,6 +344,11 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size uint* jmp_offset = NEW_RESOURCE_ARRAY(uint,nblocks); uint* jmp_size = NEW_RESOURCE_ARRAY(uint,nblocks); int* jmp_nidx = NEW_RESOURCE_ARRAY(int ,nblocks); + + // Collect worst case block paddings + int* block_worst_case_pad = NEW_RESOURCE_ARRAY(int, nblocks); + memset(block_worst_case_pad, 0, nblocks * sizeof(int)); + DEBUG_ONLY( uint *jmp_target = NEW_RESOURCE_ARRAY(uint,nblocks); ) DEBUG_ONLY( uint *jmp_rule = NEW_RESOURCE_ARRAY(uint,nblocks); ) @@ -460,6 +465,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size last_avoid_back_to_back_adr += max_loop_pad; } blk_size += max_loop_pad; + block_worst_case_pad[i + 1] = max_loop_pad; } } @@ -499,9 +505,16 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size if (bnum > i) { // adjust following block's offset offset -= adjust_block_start; } + + // This block can be a loop header, account for the padding + // in the previous block. + int block_padding = block_worst_case_pad[i]; + assert(i == 0 || block_padding == 0 || br_offs >= block_padding, "Should have at least a padding on top"); // In the following code a nop could be inserted before // the branch which will increase the backward distance. - bool needs_padding = ((uint)br_offs == last_may_be_short_branch_adr); + bool needs_padding = ((uint)(br_offs - block_padding) == last_may_be_short_branch_adr); + assert(!needs_padding || jmp_offset[i] == 0, "padding only branches at the beginning of block"); + if (needs_padding && offset <= 0) offset -= nop_size; From dd0e29f8b77a411aebfff5be0661952cd2bd5375 Mon Sep 17 00:00:00 2001 From: Paul Govereau Date: Wed, 26 Feb 2014 18:05:02 -0800 Subject: [PATCH 204/265] 6533516: Warning needed for file with future time stamps Reviewed-by: jjg, vromero --- .../classes/com/sun/tools/javac/file/RegularFileObject.java | 2 ++ .../classes/com/sun/tools/javac/resources/compiler.properties | 4 ++++ langtools/test/tools/javac/diags/examples.not-yet.txt | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java b/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java index 38f00cd3f3a..014c3b0aa63 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java @@ -71,6 +71,8 @@ class RegularFileObject extends BaseFileObject { } this.name = name; this.file = f; + if (f.lastModified() > System.currentTimeMillis()) + fileManager.log.warning("file.from.future", f); } @Override diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index abbdf4847c6..a54e14afdc5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1158,6 +1158,10 @@ compiler.misc.x.print.processor.info=\ compiler.misc.x.print.rounds=\ Round {0}:\n\tinput files: {1}\n\tannotations: {2}\n\tlast round: {3} +# 0: file name +compiler.warn.file.from.future=\ + Modification date is in the future for file {0} + ##### ## The following string will appear before all messages keyed as: diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 2676b71929b..9f227708f46 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -110,4 +110,4 @@ compiler.warn.unexpected.archive.file # Paths: zip file with u compiler.warn.unknown.enum.constant # in bad class file compiler.warn.unknown.enum.constant.reason # in bad class file compiler.warn.override.equals.but.not.hashcode # when a class overrides equals but not hashCode method from Object - +compiler.warn.file.from.future # warning for future modification times on files From 816bfaa7bc65feb559313cb159afd68060dce0db Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Thu, 27 Feb 2014 00:29:22 -0500 Subject: [PATCH 205/265] 8035766: Execute TypeAnnotate visitor at queue flush time Moved execution of TypeAnnotate visitor into Worker for type annotations Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Annotate.java | 131 +++++++++--------- .../com/sun/tools/javac/comp/Attr.java | 8 +- .../com/sun/tools/javac/comp/MemberEnter.java | 10 +- 3 files changed, 73 insertions(+), 76 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index cc0636ba257..d7b5f4a11cc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -790,44 +790,69 @@ public class Annotate { */ private void actualEnterTypeAnnotations(final List annotations, final Env env, - final Symbol s) { + final Symbol s, + final DiagnosticPosition deferPos) { Map> annotated = new LinkedHashMap<>(); Map pos = new HashMap<>(); - for (List al = annotations; !al.isEmpty(); al = al.tail) { - JCAnnotation a = al.head; - Attribute.TypeCompound tc = - enterTypeAnnotation(a, syms.annotationType, env); + JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + DiagnosticPosition prevLintPos = null; - if (tc == null) { - continue; - } - - if (annotated.containsKey(a.type.tsym)) { - if (!allowRepeatedAnnos) { - log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); - allowRepeatedAnnos = true; - } - ListBuffer l = annotated.get(a.type.tsym); - l = l.append(tc); - annotated.put(a.type.tsym, l); - pos.put(tc, a.pos()); - } else { - annotated.put(a.type.tsym, ListBuffer.of(tc)); - pos.put(tc, a.pos()); - } + if (deferPos != null) { + prevLintPos = deferredLintHandler.setPos(deferPos); } + try { - if (s != null) { - s.appendTypeAttributesWithCompletion( - new AnnotateRepeatedContext<>(env, annotated, pos, log, true)); + for (List al = annotations; !al.isEmpty(); al = al.tail) { + JCAnnotation a = al.head; + Attribute.TypeCompound tc = + enterTypeAnnotation(a, syms.annotationType, env); + + if (tc == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (!allowRepeatedAnnos) { + log.error(a.pos(), "repeatable.annotations.not.supported.in.source"); + allowRepeatedAnnos = true; + } + ListBuffer l = annotated.get(a.type.tsym); + l = l.append(tc); + annotated.put(a.type.tsym, l); + pos.put(tc, a.pos()); + } else { + annotated.put(a.type.tsym, ListBuffer.of(tc)); + pos.put(tc, a.pos()); + } + } + + if (s != null) { + s.appendTypeAttributesWithCompletion( + new AnnotateRepeatedContext<>(env, annotated, pos, log, true)); + } + } finally { + if (prevLintPos != null) + deferredLintHandler.setPos(prevLintPos); + log.useSource(prev); } } - public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym, DiagnosticPosition deferPos) { - if (allowTypeAnnos) { - tree.accept(new TypeAnnotate(env, sym, deferPos)); - } + public void annotateTypeLater(final JCTree tree, + final Env env, + final Symbol sym, + final DiagnosticPosition deferPos) { + + normal(new Annotate.Worker() { + @Override + public String toString() { + return "type annotate " + tree + " onto " + sym + " in " + sym.owner; + } + @Override + public void run() { + tree.accept(new TypeAnnotate(env, sym, deferPos)); + } + }); } /** @@ -835,64 +860,36 @@ public class Annotate { * annotations. We also need to visit type arguments, etc. */ private class TypeAnnotate extends TreeScanner { - private Env env; - private Symbol sym; + private final Env env; + private final Symbol sym; private DiagnosticPosition deferPos; - public TypeAnnotate(final Env env, final Symbol sym, DiagnosticPosition deferPos) { + public TypeAnnotate(final Env env, + final Symbol sym, + final DiagnosticPosition deferPos) { + this.env = env; this.sym = sym; this.deferPos = deferPos; } - void annotateTypeLater(final List annotations) { - if (annotations.isEmpty()) { - return; - } - - final DiagnosticPosition deferPos = this.deferPos; - - normal(new Annotate.Worker() { - @Override - public String toString() { - return "type annotate " + annotations + " onto " + sym + " in " + sym.owner; - } - @Override - public void run() { - JavaFileObject prev = log.useSource(env.toplevel.sourcefile); - DiagnosticPosition prevLintPos = null; - - if (deferPos != null) { - prevLintPos = deferredLintHandler.setPos(deferPos); - } - try { - actualEnterTypeAnnotations(annotations, env, sym); - } finally { - if (prevLintPos != null) - deferredLintHandler.setPos(prevLintPos); - log.useSource(prev); - } - } - }); - } - @Override public void visitAnnotatedType(final JCAnnotatedType tree) { - annotateTypeLater(tree.annotations); + actualEnterTypeAnnotations(tree.annotations, env, sym, deferPos); super.visitAnnotatedType(tree); } @Override public void visitTypeParameter(final JCTypeParameter tree) { - annotateTypeLater(tree.annotations); + actualEnterTypeAnnotations(tree.annotations, env, sym, deferPos); super.visitTypeParameter(tree); } @Override public void visitNewArray(final JCNewArray tree) { - annotateTypeLater(tree.annotations); + actualEnterTypeAnnotations(tree.annotations, env, sym, deferPos); for (List dimAnnos : tree.dimAnnotations) - annotateTypeLater(dimAnnos); + actualEnterTypeAnnotations(dimAnnos, env, sym, deferPos); super.visitNewArray(tree); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 7f0cded8001..f7ae9d456d7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -774,7 +774,7 @@ public class Attr extends JCTree.Visitor { // to the symbol. // This prevents having multiple type annotations, just because of // lazy constant value evaluation. - annotate.typeAnnotate(variable.init, env, null, variable.pos()); + annotate.annotateTypeLater(variable.init, env, null, variable.pos()); annotate.flush(); Type itype = attribExpr(variable.init, env, type); if (itype.constValue() != null) { @@ -1021,7 +1021,7 @@ public class Attr extends JCTree.Visitor { } // Attribute all type annotations in the body - annotate.typeAnnotate(tree.body, localEnv, m, null); + annotate.annotateTypeLater(tree.body, localEnv, m, null); annotate.flush(); // Attribute method body. @@ -1050,7 +1050,7 @@ public class Attr extends JCTree.Visitor { } else { if (tree.init != null) { // Field initializer expression need to be entered. - annotate.typeAnnotate(tree.init, env, tree.sym, tree.pos()); + annotate.annotateTypeLater(tree.init, env, tree.sym, tree.pos()); annotate.flush(); } } @@ -1111,7 +1111,7 @@ public class Attr extends JCTree.Visitor { if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; // Attribute all type annotations in the block - annotate.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); + annotate.annotateTypeLater(tree, localEnv, localEnv.info.scope.owner, null); annotate.flush(); { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 03ac3c42a3f..3e002c7d501 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -607,7 +607,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); // Visit the signature of the method. Note that // TypeAnnotate doesn't descend into the body. - annotate.typeAnnotate(tree, localEnv, m, tree.pos()); + annotate.annotateTypeLater(tree, localEnv, m, tree.pos()); if (tree.defaultValue != null) annotateDefaultValueLater(tree.defaultValue, localEnv, m); @@ -698,7 +698,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { enclScope.enter(v); } annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); - annotate.typeAnnotate(tree.vartype, env, v, tree.pos()); + annotate.annotateTypeLater(tree.vartype, env, v, tree.pos()); v.pos = tree.pos; } finally { annotate.enterDone(); @@ -939,9 +939,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { Env baseEnv = baseEnv(tree, env); if (tree.extending != null) - annotate.typeAnnotate(tree.extending, baseEnv, sym, tree.pos()); + annotate.annotateTypeLater(tree.extending, baseEnv, sym, tree.pos()); for (JCExpression impl : tree.implementing) - annotate.typeAnnotate(impl, baseEnv, sym, tree.pos()); + annotate.annotateTypeLater(impl, baseEnv, sym, tree.pos()); annotate.flush(); // Determine supertype. @@ -1010,7 +1010,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribTypeVariables(tree.typarams, baseEnv); // Do this here, where we have the symbol. for (JCTypeParameter tp : tree.typarams) - annotate.typeAnnotate(tp, baseEnv, sym, tree.pos()); + annotate.annotateTypeLater(tp, baseEnv, sym, tree.pos()); // Add default constructor if needed. if ((c.flags() & INTERFACE) == 0 && From ad1e6aab2a9cb4640a58aa92abf95768fb1af5b7 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 27 Feb 2014 09:17:58 +0100 Subject: [PATCH 206/265] 8035825: Warn instead of fail when calling the configure wrapper directly Reviewed-by: dholmes, tbell --- common/autoconf/configure | 19 ++++++++++--------- common/autoconf/configure.ac | 2 +- common/autoconf/generated-configure.sh | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/common/autoconf/configure b/common/autoconf/configure index d64b9354d4a..588a31cc42c 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -23,18 +23,19 @@ # if test "x$1" != xCHECKME; then - echo "This script cannot be run directly." + echo "WARNING: Calling the wrapper script directly is deprecated and unsupported." + echo "Not all features of configure will be available." echo "Use the 'configure' script in the top-level directory instead." - exit 1 + TOPDIR=$(cd $(dirname $0)/../.. > /dev/null && pwd) +else + # Now the next argument is the absolute top-level directory path. + # The TOPDIR variable is passed on to configure.ac. + TOPDIR="$2" + # Remove these two arguments to get to the user supplied arguments + shift + shift fi -# Now the next argument is the absolute top-level directory path. -# The TOPDIR variable is passed on to configure.ac. -TOPDIR="$2" -# Remove these two arguments to get to the user supplied arguments -shift -shift - conf_script_dir="$TOPDIR/common/autoconf" if [ "$CUSTOM_CONFIG_DIR" = "" ]; then diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 29b678a8ede..b9b374ca9c7 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -33,7 +33,7 @@ AC_PREREQ([2.69]) AC_INIT(OpenJDK, jdk8, build-dev@openjdk.java.net,,http://openjdk.java.net) -AC_CONFIG_AUX_DIR([common/autoconf/build-aux]) +AC_CONFIG_AUX_DIR([$TOPDIR/common/autoconf/build-aux]) m4_include([build-aux/pkg.m4]) # Include these first... diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 227c7fbbb07..99893855710 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -3162,7 +3162,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= -for ac_dir in common/autoconf/build-aux "$srcdir"/common/autoconf/build-aux; do +for ac_dir in $TOPDIR/common/autoconf/build-aux "$srcdir"/$TOPDIR/common/autoconf/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" @@ -3178,7 +3178,7 @@ for ac_dir in common/autoconf/build-aux "$srcdir"/common/autoconf/build-aux; do fi done if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in common/autoconf/build-aux \"$srcdir\"/common/autoconf/build-aux" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in $TOPDIR/common/autoconf/build-aux \"$srcdir\"/$TOPDIR/common/autoconf/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -4220,7 +4220,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1393327380 +DATE_WHEN_GENERATED=1393416124 ############################################################################### # From 58c97205d0d98b374e33ebb179fab14a05012ed0 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 27 Feb 2014 09:37:16 +0100 Subject: [PATCH 207/265] 8032011: nsk/stress/jck60/jck60022 crashes in src\share\vm\runtime\synchronizer.cpp:239 Biased locking's revoke_bias locks monitor in compiled frame with eliminated lock Reviewed-by: kvn, iveresov --- .../src/share/vm/runtime/biasedLocking.cpp | 2 +- .../TestLockEliminatedAtDeopt.java | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/compiler/uncommontrap/TestLockEliminatedAtDeopt.java diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp index 42e4899b251..f4ba0328baf 100644 --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp @@ -128,7 +128,7 @@ static GrowableArray* get_or_compute_monitor_info(JavaThread* thre // Walk monitors youngest to oldest for (int i = len - 1; i >= 0; i--) { MonitorInfo* mon_info = monitors->at(i); - if (mon_info->owner_is_scalar_replaced()) continue; + if (mon_info->eliminated()) continue; oop owner = mon_info->owner(); if (owner != NULL) { info->append(mon_info); diff --git a/hotspot/test/compiler/uncommontrap/TestLockEliminatedAtDeopt.java b/hotspot/test/compiler/uncommontrap/TestLockEliminatedAtDeopt.java new file mode 100644 index 00000000000..153b214c26c --- /dev/null +++ b/hotspot/test/compiler/uncommontrap/TestLockEliminatedAtDeopt.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8032011 + * @summary biased locking's revoke_bias locks monitor in compiled frame with eliminated lock + * @run main/othervm -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestLockEliminatedAtDeopt$A.m2 -XX:-BackgroundCompilation -XX:BiasedLockingStartupDelay=0 TestLockEliminatedAtDeopt + * + */ + +public class TestLockEliminatedAtDeopt { + + static class A { + void m() { + } + + // This lock is not eliminated but biased to main thread on + // first call + synchronized void m2(boolean trap) { + if (trap) { + new B(); + } + } + } + + static class B extends A { + void m() { + } + } + + static void m1(boolean trap) { + A a = new A(); + // This lock is eliminated by c2 + synchronized(a) { + a.m2(trap); + a.m(); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 20000; i++) { + m1(false); + } + // Trigger uncommon trap in A.m2() (class unloaded) and + // deoptimization of m1() (CHA invalidated). Uncommon trap + // code locks monitor in m1's frame where's it's eliminated. + m1(true); + } +} From 7fc4ffd40bf2240df8099c44adc886c4019dbd77 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 27 Feb 2014 09:40:35 +0100 Subject: [PATCH 208/265] 8035730: Configure fails in cygwin if current dir is in /home/user Reviewed-by: tbell --- common/autoconf/basics.m4 | 27 +- common/autoconf/generated-configure.sh | 413 +++++++++++++------------ 2 files changed, 221 insertions(+), 219 deletions(-) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 092c9596937..17ed7906f67 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -418,21 +418,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], # Setup basic configuration paths, and platform-specific stuff related to PATHs. AC_DEFUN_ONCE([BASIC_SETUP_PATHS], [ - # We get the top-level directory from the supporting wrappers. - AC_MSG_CHECKING([for top-level directory]) - AC_MSG_RESULT([$TOPDIR]) - BASIC_FIXUP_PATH(TOPDIR) - AC_SUBST(TOPDIR) - - # SRC_ROOT is a traditional alias for TOPDIR. - SRC_ROOT=$TOPDIR - - # Locate the directory of this script. - AUTOCONF_DIR=$TOPDIR/common/autoconf - # Save the current directory this script was started from CURDIR="$PWD" - BASIC_FIXUP_PATH(CURDIR) if test "x$OPENJDK_TARGET_OS" = "xwindows"; then PATH_SEP=";" @@ -442,6 +429,20 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS], fi AC_SUBST(PATH_SEP) + # We get the top-level directory from the supporting wrappers. + AC_MSG_CHECKING([for top-level directory]) + AC_MSG_RESULT([$TOPDIR]) + AC_SUBST(TOPDIR) + + # We can only call BASIC_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS. + BASIC_FIXUP_PATH(CURDIR) + BASIC_FIXUP_PATH(TOPDIR) + # SRC_ROOT is a traditional alias for TOPDIR. + SRC_ROOT=$TOPDIR + + # Locate the directory of this script. + AUTOCONF_DIR=$TOPDIR/common/autoconf + if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then # Add extra search paths on solaris for utilities like ar and as etc... PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 99893855710..3bf81ca7ce8 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -882,8 +882,8 @@ BUILD_LOG_WRAPPER BUILD_LOG_PREVIOUS BUILD_LOG SYS_ROOT -PATH_SEP TOPDIR +PATH_SEP ZERO_ARCHDEF DEFINE_CROSS_COMPILE_ARCH LP64 @@ -4220,7 +4220,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1393416124 +DATE_WHEN_GENERATED=1393490405 ############################################################################### # @@ -13869,143 +13869,114 @@ $as_echo "$COMPILE_TYPE" >&6; } # Continue setting up basic stuff. Most remaining code require fundamental tools. + # Save the current directory this script was started from + CURDIR="$PWD" + + if test "x$OPENJDK_TARGET_OS" = "xwindows"; then + PATH_SEP=";" + + SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` + if test $SRC_ROOT_LENGTH -gt 100; then + as_fn_error $? "Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported" "$LINENO" 5 + fi + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin release" >&5 +$as_echo_n "checking cygwin release... " >&6; } + CYGWIN_VERSION=`$UNAME -r` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_VERSION" >&5 +$as_echo "$CYGWIN_VERSION" >&6; } + WINDOWS_ENV_VENDOR='cygwin' + WINDOWS_ENV_VERSION="$CYGWIN_VERSION" + + CYGWIN_VERSION_OK=`$ECHO $CYGWIN_VERSION | $GREP ^1.7.` + if test "x$CYGWIN_VERSION_OK" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&5 +$as_echo "$as_me: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&6;} + as_fn_error $? "Cannot continue" "$LINENO" 5 + fi + if test "x$CYGPATH" = x; then + as_fn_error $? "Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin root directory as unix-style path" >&5 +$as_echo_n "checking cygwin root directory as unix-style path... " >&6; } + # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away + cygwin_winpath_root=`cd / ; cmd /c cd | grep ".*"` + # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. + CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_ROOT_PATH" >&5 +$as_echo "$CYGWIN_ROOT_PATH" >&6; } + WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" + test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + as_fn_error $? "Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c." "$LINENO" 5 + fi + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys release" >&5 +$as_echo_n "checking msys release... " >&6; } + MSYS_VERSION=`$UNAME -r` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_VERSION" >&5 +$as_echo "$MSYS_VERSION" >&6; } + + WINDOWS_ENV_VENDOR='msys' + WINDOWS_ENV_VERSION="$MSYS_VERSION" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys root directory as unix-style path" >&5 +$as_echo_n "checking msys root directory as unix-style path... " >&6; } + # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away + MSYS_ROOT_PATH=`cd / ; cmd /c cd | grep ".*"` + + windows_path="$MSYS_ROOT_PATH" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + MSYS_ROOT_PATH="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + MSYS_ROOT_PATH="$unix_path" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_ROOT_PATH" >&5 +$as_echo "$MSYS_ROOT_PATH" >&6; } + WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" + else + as_fn_error $? "Unknown Windows environment. Neither cygwin nor msys was detected." "$LINENO" 5 + fi + + # Test if windows or unix (cygwin/msys) find is first in path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of 'find' is first on the PATH" >&5 +$as_echo_n "checking what kind of 'find' is first on the PATH... " >&6; } + FIND_BINARY_OUTPUT=`find --version 2>&1` + if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix style" >&5 +$as_echo "unix style" >&6; } + elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5 +$as_echo "Windows" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&5 +$as_echo "$as_me: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&5 +$as_echo "$as_me: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&6;} + as_fn_error $? "Cannot continue" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 +$as_echo "unknown" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: It seems that your find utility is non-standard." >&5 +$as_echo "$as_me: WARNING: It seems that your find utility is non-standard." >&2;} + fi + + else + PATH_SEP=":" + fi + + # We get the top-level directory from the supporting wrappers. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for top-level directory" >&5 $as_echo_n "checking for top-level directory... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOPDIR" >&5 $as_echo "$TOPDIR" >&6; } - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - # Input might be given as Windows format, start by converting to - # unix format. - path="$TOPDIR" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of TOPDIR" "$LINENO" 5 - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - TOPDIR="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$TOPDIR" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - TOPDIR="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$TOPDIR" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of TOPDIR, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - TOPDIR="`cd "$path"; $THEPWDCMD -L`" - fi - - - - # SRC_ROOT is a traditional alias for TOPDIR. - SRC_ROOT=$TOPDIR - - # Locate the directory of this script. - AUTOCONF_DIR=$TOPDIR/common/autoconf - - # Save the current directory this script was started from - CURDIR="$PWD" + # We can only call BASIC_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS. if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then @@ -14129,102 +14100,132 @@ $as_echo "$as_me: The path of CURDIR, which resolves as \"$path\", is invalid." fi - if test "x$OPENJDK_TARGET_OS" = "xwindows"; then - PATH_SEP=";" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - SRC_ROOT_LENGTH=`$THEPWDCMD -L|$WC -m` - if test $SRC_ROOT_LENGTH -gt 100; then - as_fn_error $? "Your base path is too long. It is $SRC_ROOT_LENGTH characters long, but only 100 is supported" "$LINENO" 5 + # Input might be given as Windows format, start by converting to + # unix format. + path="$TOPDIR" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of TOPDIR" "$LINENO" 5 fi - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin release" >&5 -$as_echo_n "checking cygwin release... " >&6; } - CYGWIN_VERSION=`$UNAME -r` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_VERSION" >&5 -$as_echo "$CYGWIN_VERSION" >&6; } - WINDOWS_ENV_VENDOR='cygwin' - WINDOWS_ENV_VERSION="$CYGWIN_VERSION" + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. - CYGWIN_VERSION_OK=`$ECHO $CYGWIN_VERSION | $GREP ^1.7.` - if test "x$CYGWIN_VERSION_OK" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&5 -$as_echo "$as_me: Your cygwin is too old. You are running $CYGWIN_VERSION, but at least cygwin 1.7 is required. Please upgrade." >&6;} - as_fn_error $? "Cannot continue" "$LINENO" 5 + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" fi - if test "x$CYGPATH" = x; then - as_fn_error $? "Something is wrong with your cygwin installation since I cannot find cygpath.exe in your path" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking cygwin root directory as unix-style path" >&5 -$as_echo_n "checking cygwin root directory as unix-style path... " >&6; } - # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away - cygwin_winpath_root=`cd / ; cmd /c cd | grep ".*"` - # Force cygpath to report the proper root by including a trailing space, and then stripping it off again. - CYGWIN_ROOT_PATH=`$CYGPATH -u "$cygwin_winpath_root " | $CUT -f 1 -d " "` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGWIN_ROOT_PATH" >&5 -$as_echo "$CYGWIN_ROOT_PATH" >&6; } - WINDOWS_ENV_ROOT_PATH="$CYGWIN_ROOT_PATH" - test_cygdrive_prefix=`$ECHO $CYGWIN_ROOT_PATH | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - as_fn_error $? "Your cygdrive prefix is not /cygdrive. This is currently not supported. Change with mount -c." "$LINENO" 5 + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" fi + fi + + + if test "x$path" != "x$new_path"; then + TOPDIR="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} + fi + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys release" >&5 -$as_echo_n "checking msys release... " >&6; } - MSYS_VERSION=`$UNAME -r` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_VERSION" >&5 -$as_echo "$MSYS_VERSION" >&6; } - WINDOWS_ENV_VENDOR='msys' - WINDOWS_ENV_VERSION="$MSYS_VERSION" + path="$TOPDIR" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking msys root directory as unix-style path" >&5 -$as_echo_n "checking msys root directory as unix-style path... " >&6; } - # The cmd output ends with Windows line endings (CR/LF), the grep command will strip that away - MSYS_ROOT_PATH=`cd / ; cmd /c cd | grep ".*"` - windows_path="$MSYS_ROOT_PATH" + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then unix_path=`$CYGPATH -u "$windows_path"` - MSYS_ROOT_PATH="$unix_path" + new_path="$unix_path" elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - MSYS_ROOT_PATH="$unix_path" + new_path="$unix_path" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSYS_ROOT_PATH" >&5 -$as_echo "$MSYS_ROOT_PATH" >&6; } - WINDOWS_ENV_ROOT_PATH="$MSYS_ROOT_PATH" - else - as_fn_error $? "Unknown Windows environment. Neither cygwin nor msys was detected." "$LINENO" 5 + if test "x$path" != "x$new_path"; then + TOPDIR="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting TOPDIR to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting TOPDIR to \"$new_path\"" >&6;} fi - # Test if windows or unix (cygwin/msys) find is first in path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of 'find' is first on the PATH" >&5 -$as_echo_n "checking what kind of 'find' is first on the PATH... " >&6; } - FIND_BINARY_OUTPUT=`find --version 2>&1` - if test "x`echo $FIND_BINARY_OUTPUT | $GREP GNU`" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix style" >&5 -$as_echo "unix style" >&6; } - elif test "x`echo $FIND_BINARY_OUTPUT | $GREP FIND`" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5 -$as_echo "Windows" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&5 -$as_echo "$as_me: Your path contains Windows tools (C:\Windows\system32) before your unix (cygwin or msys) tools." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&5 -$as_echo "$as_me: This will not work. Please correct and make sure /usr/bin (or similar) is first in path." >&6;} - as_fn_error $? "Cannot continue" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 -$as_echo "unknown" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: It seems that your find utility is non-standard." >&5 -$as_echo "$as_me: WARNING: It seems that your find utility is non-standard." >&2;} - fi + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") else - PATH_SEP=":" + # We're on a posix platform. Hooray! :) + path="$TOPDIR" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of TOPDIR, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of TOPDIR, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + TOPDIR="`cd "$path"; $THEPWDCMD -L`" fi + # SRC_ROOT is a traditional alias for TOPDIR. + SRC_ROOT=$TOPDIR + + # Locate the directory of this script. + AUTOCONF_DIR=$TOPDIR/common/autoconf if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then # Add extra search paths on solaris for utilities like ar and as etc... From ba2326e19f119c6326dcae10d702e401eb15666d Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 27 Feb 2014 10:34:55 +0100 Subject: [PATCH 209/265] 8035648: Don't use Handle in java_lang_String::print Reviewed-by: coleenp, pliden --- hotspot/src/share/vm/classfile/javaClasses.cpp | 11 +++++------ hotspot/src/share/vm/classfile/javaClasses.hpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 3 +-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index d9bd3a4d713..20f50588400 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -461,12 +461,11 @@ bool java_lang_String::equals(oop str1, oop str2) { return true; } -void java_lang_String::print(Handle java_string, outputStream* st) { - oop obj = java_string(); - assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string"); - typeArrayOop value = java_lang_String::value(obj); - int offset = java_lang_String::offset(obj); - int length = java_lang_String::length(obj); +void java_lang_String::print(oop java_string, outputStream* st) { + assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); + typeArrayOop value = java_lang_String::value(java_string); + int offset = java_lang_String::offset(java_string); + int length = java_lang_String::length(java_string); int end = MIN2(length, 100); if (value == NULL) { diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index ffccf2f0e0c..7cbaac925e7 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -198,7 +198,7 @@ class java_lang_String : AllStatic { } // Debugging - static void print(Handle java_string, outputStream* st); + static void print(oop java_string, outputStream* st); friend class JavaClasses; }; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 62f7ffbf370..6344af71b6d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2987,8 +2987,7 @@ void InstanceKlass::oop_print_on(oop obj, outputStream* st) { offset <= (juint) value->length() && offset + length <= (juint) value->length()) { st->print(BULLET"string: "); - Handle h_obj(obj); - java_lang_String::print(h_obj, st); + java_lang_String::print(obj, st); st->cr(); if (!WizardMode) return; // that is enough } From 959bdfb211b97b10cc21009a724b35cf32029e33 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 27 Feb 2014 10:36:50 +0100 Subject: [PATCH 210/265] 8035746: Add missing Klass::oop_is_instanceClassLoader() function Reviewed-by: mgerdin, coleenp --- hotspot/src/share/vm/oops/klass.cpp | 18 ++++++++++++++++++ hotspot/src/share/vm/oops/klass.hpp | 1 + hotspot/src/share/vm/oops/oop.hpp | 13 +++++++------ hotspot/src/share/vm/oops/oop.inline.hpp | 13 +++++++------ hotspot/src/share/vm/prims/jni.cpp | 2 ++ 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index adca246aaa9..0717079e002 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -692,3 +692,21 @@ bool Klass::verify_itable_index(int i) { } #endif + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class TestKlass { + public: + static void test_oop_is_instanceClassLoader() { + assert(SystemDictionary::ClassLoader_klass()->oop_is_instanceClassLoader(), "assert"); + assert(!SystemDictionary::String_klass()->oop_is_instanceClassLoader(), "assert"); + } +}; + +void TestKlass_test() { + TestKlass::test_oop_is_instanceClassLoader(); +} + +#endif diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index a31a2357355..fd4701c6e4f 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -498,6 +498,7 @@ class Klass : public Metadata { virtual bool oop_is_objArray_slow() const { return false; } virtual bool oop_is_typeArray_slow() const { return false; } public: + virtual bool oop_is_instanceClassLoader() const { return false; } virtual bool oop_is_instanceMirror() const { return false; } virtual bool oop_is_instanceRef() const { return false; } diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 2013c3ea758..2ea801d627a 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -109,12 +109,13 @@ class oopDesc { int size_given_klass(Klass* klass); // type test operations (inlined in oop.inline.h) - bool is_instance() const; - bool is_instanceMirror() const; - bool is_instanceRef() const; - bool is_array() const; - bool is_objArray() const; - bool is_typeArray() const; + bool is_instance() const; + bool is_instanceMirror() const; + bool is_instanceClassLoader() const; + bool is_instanceRef() const; + bool is_array() const; + bool is_objArray() const; + bool is_typeArray() const; private: // field addresses in oop diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 4e81252b548..adc40333f1b 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -147,12 +147,13 @@ inline void oopDesc::init_mark() { set_mark(markOopDesc::proto inline bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); } -inline bool oopDesc::is_instance() const { return klass()->oop_is_instance(); } -inline bool oopDesc::is_instanceMirror() const { return klass()->oop_is_instanceMirror(); } -inline bool oopDesc::is_instanceRef() const { return klass()->oop_is_instanceRef(); } -inline bool oopDesc::is_array() const { return klass()->oop_is_array(); } -inline bool oopDesc::is_objArray() const { return klass()->oop_is_objArray(); } -inline bool oopDesc::is_typeArray() const { return klass()->oop_is_typeArray(); } +inline bool oopDesc::is_instance() const { return klass()->oop_is_instance(); } +inline bool oopDesc::is_instanceClassLoader() const { return klass()->oop_is_instanceClassLoader(); } +inline bool oopDesc::is_instanceMirror() const { return klass()->oop_is_instanceMirror(); } +inline bool oopDesc::is_instanceRef() const { return klass()->oop_is_instanceRef(); } +inline bool oopDesc::is_array() const { return klass()->oop_is_array(); } +inline bool oopDesc::is_objArray() const { return klass()->oop_is_objArray(); } +inline bool oopDesc::is_typeArray() const { return klass()->oop_is_typeArray(); } inline void* oopDesc::field_base(int offset) const { return (void*)&((char*)this)[offset]; } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 19b20537ae6..b778f606998 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3877,6 +3877,7 @@ void TestMetaspaceAux_test(); void TestMetachunk_test(); void TestVirtualSpaceNode_test(); void TestNewSize_test(); +void TestKlass_test(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -3900,6 +3901,7 @@ void execute_internal_vm_tests() { run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); run_unit_test(TestNewSize_test()); + run_unit_test(TestKlass_test()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif From 74db1cc7536db715b8cc832ba2d4618783cb1e9a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 27 Feb 2014 20:40:24 +0100 Subject: [PATCH 211/265] 8035970: PPC64: fix ad file after 8027754: Enable loop optimizations for loops with MathExact Reviewed-by: kvn --- hotspot/src/cpu/ppc/vm/ppc.ad | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 01d5ffb8314..6006c1acaf6 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2360,18 +2360,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() { return RegMask(); } -const RegMask Matcher::mathExactI_result_proj_mask() { - return RARG4_BITS64_REG_mask(); -} - -const RegMask Matcher::mathExactL_result_proj_mask() { - return RARG4_BITS64_REG_mask(); -} - -const RegMask Matcher::mathExactI_flags_proj_mask() { - return INT_FLAGS_mask(); -} - %} //----------ENCODING BLOCK----------------------------------------------------- @@ -7572,16 +7560,6 @@ instruct getAndSetN(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src) %{ //----------Arithmetic Instructions-------------------------------------------- // Addition Instructions -// PPC has no instruction setting overflow of 32-bit integer. -//instruct addExactI_rReg(rarg4RegI dst, rRegI src, flagsReg cr) %{ -// match(AddExactI dst src); -// effect(DEF cr); -// -// format %{ "ADD $dst, $dst, $src \t// addExact int, sets $cr" %} -// ins_encode( enc_add(dst, dst, src) ); -// ins_pipe(pipe_class_default); -//%} - // Register Addition instruct addI_reg_reg(iRegIdst dst, iRegIsrc_iRegL2Isrc src1, iRegIsrc_iRegL2Isrc src2) %{ match(Set dst (AddI src1 src2)); From e97bf8b14617fc9960ab3b79315de3dee5ca7fec Mon Sep 17 00:00:00 2001 From: Paul Govereau Date: Thu, 27 Feb 2014 11:47:39 -0800 Subject: [PATCH 212/265] 8035972: missing test file for 8034048 Reviewed-by: jjg, vromero --- .../javac/varargs/MethodHandleCrash.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 langtools/test/tools/javac/varargs/MethodHandleCrash.java diff --git a/langtools/test/tools/javac/varargs/MethodHandleCrash.java b/langtools/test/tools/javac/varargs/MethodHandleCrash.java new file mode 100644 index 00000000000..a95862d7d27 --- /dev/null +++ b/langtools/test/tools/javac/varargs/MethodHandleCrash.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034048 + * @summary javac crash with method references plus lambda plus var args + * @author govereau + * + * @compile MethodHandleCrash.java + */ +public interface MethodHandleCrash { + static void functional(T... input) { + java.util.function.Consumer c = MethodHandleCrash::functional; + } +} From 25c2444601d3e8e14e2a03658ad3fde847c13d91 Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Thu, 27 Feb 2014 13:57:57 -0800 Subject: [PATCH 213/265] 8033287: Reduce the size of the endPosTable Co-authored-by: Charlie Turner Reviewed-by: jjg --- .../sun/tools/javac/parser/JavacParser.java | 18 +- .../sun/tools/javac/util/IntHashTable.java | 198 ++++++++++++++++++ 2 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 49f68b13ae6..279f400baf4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -4055,15 +4055,16 @@ public class JavacParser implements Parser { */ protected static class SimpleEndPosTable extends AbstractEndPosTable { - private final Map endPosMap; + private final IntHashTable endPosMap; SimpleEndPosTable(JavacParser parser) { super(parser); - endPosMap = new HashMap<>(); + endPosMap = new IntHashTable(); } public void storeEnd(JCTree tree, int endpos) { - endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos); + endPosMap.putAtIndex(tree, errorEndPos > endpos ? errorEndPos : endpos, + endPosMap.lookup(tree)); } protected T to(T t) { @@ -4077,14 +4078,15 @@ public class JavacParser implements Parser { } public int getEndPos(JCTree tree) { - Integer value = endPosMap.get(tree); - return (value == null) ? Position.NOPOS : value; + int value = endPosMap.getFromIndex(endPosMap.lookup(tree)); + // As long as Position.NOPOS==-1, this just returns value. + return (value == -1) ? Position.NOPOS : value; } public int replaceTree(JCTree oldTree, JCTree newTree) { - Integer pos = endPosMap.remove(oldTree); - if (pos != null) { - endPosMap.put(newTree, pos); + int pos = endPosMap.remove(oldTree); + if (pos != -1) { + storeEnd(newTree, pos); return pos; } return Position.NOPOS; diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java b/langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java new file mode 100644 index 00000000000..ca820d278ce --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.util; + +/** + * A hash table that maps Object to int. + * + * This is a custom hash table optimised for the Object -> int + * maps. This is done to avoid unnecessary object allocation in the image set. + * + * @author Charles Turner + * @author Per Bothner + */ +public class IntHashTable { + private static final int DEFAULT_INITIAL_SIZE = 64; + protected Object[] objs; // the domain set + protected int[] ints; // the image set + protected int mask; // used to clip int's into the domain + protected int num_bindings; // the number of mappings (including DELETED) + private final static Object DELETED = new Object(); + + /** + * Construct an Object -> int hash table. + * + * The default size of the hash table is 64 mappings. + */ + public IntHashTable() { + objs = new Object[DEFAULT_INITIAL_SIZE]; + ints = new int[DEFAULT_INITIAL_SIZE]; + mask = DEFAULT_INITIAL_SIZE - 1; + } + + /** + * Construct an Object -> int hash table with a specified amount of mappings. + * @param capacity The number of default mappings in this hash table. + */ + public IntHashTable(int capacity) { + int log2Size = 4; + while (capacity > (1 << log2Size)) { + log2Size++; + } + capacity = 1 << log2Size; + objs = new Object[capacity]; + ints = new int[capacity]; + mask = capacity - 1; + } + + /** + * Compute the hash code of a given object. + * + * @param key The object whose hash code is to be computed. + * @return zero if the object is null, otherwise the identityHashCode + */ + public int hash(Object key) { + return System.identityHashCode(key); + } + + /** + * Find either the index of a key's value, or the index of an available space. + * + * @param key The key to whose value you want to find. + * @param hash The hash code of this key. + * @return Either the index of the key's value, or an index pointing to + * unoccupied space. + */ + public int lookup(Object key, int hash) { + Object node; + int hash1 = hash ^ (hash >>> 15); + int hash2 = (hash ^ (hash << 6)) | 1; //ensure coprimeness + int deleted = -1; + for (int i = hash1 & mask;; i = (i + hash2) & mask) { + node = objs[i]; + if (node == key) + return i; + if (node == null) + return deleted >= 0 ? deleted : i; + if (node == DELETED && deleted < 0) + deleted = i; + } + } + + /** + * Lookup a given key's value in the hash table. + * + * @param key The key whose value you want to find. + * @return Either the index of the key's value, or an index pointing to + * unoccupied space. + */ + public int lookup(Object key) { + return lookup(key, hash(key)); + } + + /** + * Return the value stored at the specified index in the table. + * + * @param index The index to inspect, as returned from {@link #lookup} + * @return A non-negative integer if the index contains a non-null + * value, or -1 if it does. + */ + public int getFromIndex(int index) { + Object node = objs[index]; + return node == null || node == DELETED ? -1 : ints[index]; + } + + /** + * Associates the specified key with the specified value in this map. + * + * @param key key with which the specified value is to be associated. + * @param value value to be associated with the specified key. + * @param index the index at which to place this binding, as returned + * from {@link #lookup}. + * @return previous value associated with specified key, or -1 if there was + * no mapping for key. + */ + public int putAtIndex(Object key, int value, int index) { + Object old = objs[index]; + if (old == null || old == DELETED) { + objs[index] = key; + ints[index] = value; + if (old != DELETED) + num_bindings++; + if (3 * num_bindings >= 2 * objs.length) + rehash(); + return -1; + } else { // update existing mapping + int oldValue = ints[index]; + ints[index] = value; + return oldValue; + } + } + + public int remove(Object key) { + int index = lookup(key); + Object old = objs[index]; + if (old == null || old == DELETED) + return -1; + objs[index] = DELETED; + return ints[index]; + } + + /** + * Expand the hash table when it exceeds the load factor. + * + * Rehash the existing objects. + */ + protected void rehash() { + Object[] oldObjsTable = objs; + int[] oldIntsTable = ints; + int oldCapacity = oldObjsTable.length; + int newCapacity = oldCapacity << 1; + Object[] newObjTable = new Object[newCapacity]; + int[] newIntTable = new int[newCapacity]; + int newMask = newCapacity - 1; + objs = newObjTable; + ints = newIntTable; + mask = newMask; + num_bindings = 0; // this is recomputed below + Object key; + for (int i = oldIntsTable.length; --i >= 0;) { + key = oldObjsTable[i]; + if (key != null && key != DELETED) + putAtIndex(key, oldIntsTable[i], lookup(key, hash(key))); + } + } + + /** + * Removes all mappings from this map. + */ + public void clear() { + for (int i = objs.length; --i >= 0;) { + objs[i] = null; + } + num_bindings = 0; + } +} From 76e336a948cdd36f05695a08ecd2a8f5fc5ddf62 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 28 Feb 2014 08:40:27 +0800 Subject: [PATCH 214/265] 8035759: [parfait] JNI exception pending in jdk/src/windows/native/sun/security/krb5/NativeCreds.c Reviewed-by: valeriep --- .../native/sun/security/krb5/NativeCreds.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c index 7431333dc59..ab0ee036e6b 100644 --- a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c +++ b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c @@ -463,6 +463,10 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ netypes = (*env)->GetArrayLength(env, jetypes); etypes = (jint *) (*env)->GetIntArrayElements(env, jetypes, NULL); + if (etypes == NULL) { + break; + } + // check TGT validity if (native_debug) { printf("LSA: TICKET SessionKey KeyType is %d\n", msticket->SessionKey.KeyType); @@ -952,8 +956,7 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName, if (native_debug) { printf("LSA: Can't allocate String array for Principal\n"); } - LocalFree(realm); - return principal; + goto cleanup; } for (i=0; iNewString(env, (const jchar*)scanner->Buffer, scanner->Length/sizeof(WCHAR)); + + if (tempString == NULL) { + goto cleanup; + } + // Set the String into the StringArray (*env)->SetObjectArrayElement(env, stringArray, i, tempString); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + // Do I have to worry about storage reclamation here? } // now set the realm in the principal realmLen = (ULONG)wcslen((PWCHAR)realm); realmStr = (*env)->NewString(env, (PWCHAR)realm, (USHORT)realmLen); + if (realmStr == NULL) { + goto cleanup; + } + principal = (*env)->NewObject(env, principalNameClass, principalNameConstructor, stringArray, realmStr); +cleanup: // free local resources LocalFree(realm); From ee21184b1797650d9a8130eb1e5e76b8161288a0 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Fri, 28 Feb 2014 12:57:35 +0400 Subject: [PATCH 215/265] 7195249: Some jtreg tests use hard coded ports Use Utils.getFreePort() and launch the tests by java code Reviewed-by: jbachorik, sla --- jdk/test/ProblemList.txt | 3 - jdk/test/sun/management/jmxremote/RunTest.sh | 4 +- .../bootstrap/AbstractFilePermissionTest.java | 202 ++++++++++++++ .../management/jmxremote/bootstrap/Dummy.java | 38 +++ .../bootstrap/LocalManagementTest.java | 78 ++++-- .../bootstrap/PasswordFilePermissionTest.java | 64 +++++ .../bootstrap/PasswordFilePermissionTest.sh | 134 ---------- .../jmxremote/bootstrap/RmiBootstrapTest.java | 247 ++++++++---------- .../jmxremote/bootstrap/RmiBootstrapTest.sh | 7 +- .../bootstrap/RmiRegistrySslTest.java | 226 ++++++++++++---- .../jmxremote/bootstrap/RmiRegistrySslTest.sh | 64 ----- .../bootstrap/RmiRegistrySslTestApp.java | 92 +++++++ .../bootstrap/RmiSslBootstrapTest.sh | 6 +- .../bootstrap/RmiSslNoKeyStoreTest.java | 2 - .../SSLConfigFilePermissionTest.java | 69 +++++ .../bootstrap/SSLConfigFilePermissionTest.sh | 128 --------- .../jmxremote/bootstrap/TestLogger.java | 1 - .../bootstrap/rmiregistry.properties | 2 +- .../bootstrap/rmiregistryssl.properties | 2 +- 19 files changed, 816 insertions(+), 553 deletions(-) create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/Dummy.java create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java delete mode 100644 jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh delete mode 100644 jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTestApp.java create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java delete mode 100644 jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 8126fbf8d3b..8c5f946415d 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -127,9 +127,6 @@ java/lang/reflect/Method/invoke/TestPrivateInterfaceMethodReflect.java generic-a # jdk_management -# 8028150 -sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh windows-all - ############################################################################ # jdk_jmx diff --git a/jdk/test/sun/management/jmxremote/RunTest.sh b/jdk/test/sun/management/jmxremote/RunTest.sh index ae94265e9b8..e9a924a89b8 100644 --- a/jdk/test/sun/management/jmxremote/RunTest.sh +++ b/jdk/test/sun/management/jmxremote/RunTest.sh @@ -25,9 +25,9 @@ # No need to compile (now done by JTReg tags in calling file) # echo ${TESTJAVA}/bin/java ${TESTVMOPTS} -Dtest.src=${TESTCLASSES} \ - -classpath ${TESTCLASSES} $* || exit 20 + -classpath ${TESTCLASSPATH} $* || exit 20 ${TESTJAVA}/bin/java ${TESTVMOPTS} -Dtest.src=${TESTCLASSES} \ - -classpath ${TESTCLASSES} $* || exit 20 + -classpath ${TESTCLASSPATH} $* || exit 20 exit 0 diff --git a/jdk/test/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java b/jdk/test/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java new file mode 100644 index 00000000000..a2e0c892003 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/AbstractFilePermissionTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.testlibrary.OutputAnalyzer; +import jdk.testlibrary.Platform; +import jdk.testlibrary.ProcessTools; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.PosixFilePermission; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Change file permission for out-of-the-box management an do test used by + * PasswordFilePermissionTest and SSLConfigFilePermissionTest tests + * + * @author Taras Ledkov + */ +public abstract class AbstractFilePermissionTest { + private final String TEST_CLASS_PATH = System.getProperty("test.class.path"); + protected final String TEST_CLASSES = System.getProperty("test.classes"); + protected final FileSystem FS = FileSystems.getDefault(); + private int MAX_GET_FREE_PORT_TRIES = 10; + + protected final Path libDir = FS.getPath(TEST_CLASSES, "lib"); + protected final Path mgmt = libDir.resolve("management.properties"); + private final String mp = "-Dcom.sun.management.config.file=" + mgmt.toFile().getAbsolutePath(); + private final String className = "Dummy"; + private int failures = 0; + + protected final Path file2PermissionTest; + + protected AbstractFilePermissionTest(String fileName2PermissionTest) { + this.file2PermissionTest = libDir.resolve(fileName2PermissionTest); + + try { + MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10")); + } catch (NumberFormatException ex) { + ex.printStackTrace(); + } + } + + + public static void createFile(Path path, String... content) throws IOException { + if (Files.exists(path) && Files.isRegularFile(path)) { + try { + Files.delete(path); + } catch (Exception ex) { + System.out.println("WARNING: " + path.toFile().getAbsolutePath() + " already exists - unable to remove old copy"); + ex.printStackTrace(); + } + } + + try (BufferedWriter bw = Files.newBufferedWriter(path, Charset.defaultCharset())) { + for (String str : content) { + bw.write(str, 0, str.length()); + bw.newLine(); + } + } + } + + public boolean skipTest() { + if ((TEST_CLASSES == null) || ("".equals(TEST_CLASSES))) { + System.out.println("Test is designed to be run from jtreg only"); + return true; + } + + if (!Platform.isLinux() && !Platform.isSolaris()) { + System.out.println("Test not designed to run on this operating system, skipping..."); + return true; + } + return false; + } + + protected abstract void testSetup() throws IOException; + + public void runTest(String[] args) throws Exception { + + if (skipTest()) { + return; + } + + Files.deleteIfExists(mgmt); + Files.deleteIfExists(file2PermissionTest); + libDir.toFile().mkdir(); + + testSetup(); + + try { + test1(); + test2(); + + if (failures == 0) { + System.out.println("All test(s) passed"); + } else { + throw new Error(String.format("%d test(s) failed", failures)); + } + } finally { + resetPasswordFilePermission(); + } + } + + /** + * Test 1 - SSL config file is secure - VM should start + */ + private void test1() throws Exception { + final Set perms_0700 = new HashSet<>(); + perms_0700.add(PosixFilePermission.OWNER_WRITE); + perms_0700.add(PosixFilePermission.OWNER_READ); + perms_0700.add(PosixFilePermission.OWNER_EXECUTE); + Files.setPosixFilePermissions(file2PermissionTest, perms_0700); + + if (doTest() != 0) { + ++failures; + } + } + + /** + * Test 1 - SSL config file is secure - VM should start + */ + private void test2() throws Exception { + final Set perms = Files.getPosixFilePermissions(file2PermissionTest); + perms.add(PosixFilePermission.OTHERS_READ); + perms.add(PosixFilePermission.OTHERS_EXECUTE); + Files.setPosixFilePermissions(file2PermissionTest, perms); + + if (doTest() == 0) { + ++failures; + } + } + + private int doTest() throws Exception { + + for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) { + final String pp = "-Dcom.sun.management.jmxremote.port=" + jdk.testlibrary.Utils.getFreePort(); + + List command = new ArrayList<>(); + command.addAll(jdk.testlibrary.Utils.getVmOptions()); + command.add(mp); + command.add(pp); + command.add("-cp"); + command.add(TEST_CLASSES); + command.add(className); + + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + command.toArray(new String[command.size()])); + + System.out.println("test cmdline: " + Arrays.toString(processBuilder.command().toArray()).replace(",", "")); + Process p = processBuilder.start(); + OutputAnalyzer output = new OutputAnalyzer(p); + + System.out.println("test output:"); + System.out.println(output.getOutput()); + + if ((p.exitValue() == 0) || + !output.getOutput().contains("Exception thrown by the agent : " + + "java.rmi.server.ExportException: Port already in use")) { + return p.exitValue(); + } + } + + return -1; + } + + private void resetPasswordFilePermission() throws Exception { + final Set perms_0777 = new HashSet<>(); + Arrays.asList(PosixFilePermission.values()).stream().forEach(p -> { + perms_0777.add(p); + }); + Files.setPosixFilePermissions(file2PermissionTest, perms_0777); + } +} diff --git a/jdk/test/sun/management/jmxremote/bootstrap/Dummy.java b/jdk/test/sun/management/jmxremote/bootstrap/Dummy.java new file mode 100644 index 00000000000..94aadafcd51 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/Dummy.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.List; + +/** + * A dummy test "application" used by unit tests - + * SSLConfigFilePermissionTest.java + * + * @author Taras Ledkov + */ +class Dummy { + public static void main(String[] args) { + System.out.println("Inside main method..."); + } +} diff --git a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java index 1d4bbb1fb79..d02d43e68de 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java +++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java @@ -22,6 +22,7 @@ */ import java.io.File; +import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.FileSystem; @@ -32,7 +33,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import jdk.testlibrary.ProcessTools; /** * @test @@ -43,15 +43,25 @@ import jdk.testlibrary.ProcessTools; * TestManager will attempt a connection to the address obtained from * both agent properties and jvmstat buffer. * @build jdk.testlibrary.ProcessTools + * @build jdk.testlibrary.Utils * @build TestManager TestApplication * @run main/othervm/timeout=300 -XX:+UsePerfData LocalManagementTest */ +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; + public class LocalManagementTest { - private static final String TEST_CLASSPATH = System.getProperty("test.class.path"); - private static final String TEST_JDK = System.getProperty("test.jdk"); + private static final String TEST_CLASSPATH = System.getProperty("test.class.path"); + private static final String TEST_JDK = System.getProperty("test.jdk"); + private static int MAX_GET_FREE_PORT_TRIES = 10; public static void main(String[] args) throws Exception { + try { + MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10")); + } catch (NumberFormatException ex) { + } + int failures = 0; for(Method m : LocalManagementTest.class.getDeclaredMethods()) { if (Modifier.isStatic(m.getModifiers()) && @@ -103,29 +113,49 @@ public class LocalManagementTest { private static boolean test4() throws Exception { Path agentPath = findAgent(); if (agentPath != null) { - ProcessBuilder builder = ProcessTools.createJavaProcessBuilder( - "-javaagent:" + agentPath.toString() + - "=com.sun.management.jmxremote.port=7775," + - "com.sun.management.jmxremote.authenticate=false," + - "com.sun.management.jmxremote.ssl=false", - "-cp", - TEST_CLASSPATH, - "TestApplication", - "-exit" - ); - Process prc = null; - try { - prc = ProcessTools.startProcess( - "TestApplication", - builder + for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) { + ProcessBuilder builder = ProcessTools.createJavaProcessBuilder( + "-javaagent:" + agentPath.toString() + + "=com.sun.management.jmxremote.port=" + Utils.getFreePort() + "," + + "com.sun.management.jmxremote.authenticate=false," + + "com.sun.management.jmxremote.ssl=false", + "-cp", + TEST_CLASSPATH, + "TestApplication", + "-exit" ); - int exitCode = prc.waitFor(); - return exitCode == 0; - } finally { - if (prc != null) { - prc.destroy(); + + Process prc = null; + final AtomicReference isBindExceptionThrown = new AtomicReference<>(); + isBindExceptionThrown.set(new Boolean(false)); + try { + prc = ProcessTools.startProcess( + "TestApplication", + builder, + (String line) -> { + if (line.contains("Exception thrown by the agent : " + + "java.rmi.server.ExportException: Port already in use")) { + isBindExceptionThrown.set(new Boolean(true)); + } + }); + prc.waitFor(); + + if (prc.exitValue() == 0) { + return true; + } + + if (isBindExceptionThrown.get().booleanValue()) { + System.out.println("'Port already in use' error detected. Try again"); + } else { + return false; + } + } finally { + if (prc != null) { + prc.destroy(); + prc.waitFor(); + } } } } @@ -239,4 +269,4 @@ public class LocalManagementTest { } } } -} +} \ No newline at end of file diff --git a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java new file mode 100644 index 00000000000..cce5bc2c8a0 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; + +/** + * @test + * @library /lib/testlibrary + * @bug 6557093 + * @summary Check SSL config file permission for out-of-the-box management + * @build jdk.testlibrary.Utils + * @build jdk.testlibrary.ProcessTools + * @build jdk.testlibrary.OutputAnalyzer + * @build AbstractFilePermissionTest + * @build Dummy + * @run main/timeout=300 PasswordFilePermissionTest + * + * @author Taras Ledkov + */ +public class PasswordFilePermissionTest extends AbstractFilePermissionTest { + + private PasswordFilePermissionTest() { + super("jmxremote.passwordconfig"); + } + + public void testSetup() throws IOException { + createFile(mgmt, + "# management.properties", + "com.sun.management.jmxremote.ssl=false", + "com.sun.management.jmxremote.password.file=" + file2PermissionTest.toFile().getAbsolutePath()); + + createFile(file2PermissionTest, + "# jmxremote.password\n"); + } + + public static void main(String[] args) throws Exception { + PasswordFilePermissionTest test = new PasswordFilePermissionTest(); + + test.runTest(args); + } + +} + + diff --git a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh deleted file mode 100644 index fe1fec654a7..00000000000 --- a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please 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 5008047 -# @summary Check password file permission for out-of-the-box management -# -# @run shell PasswordFilePermissionTest.sh - -createJavaFile() -{ - cat << EOF > $1/$2.java - class $2 { - public static void main(String[] args) { - System.out.println("Inside main method..."); - } - } -EOF -} - -createConfigFile() { - cat << EOF > $1 -# management.properties -com.sun.management.jmxremote.ssl=false -com.sun.management.jmxremote.password.file=$2 -EOF -} - -createPasswordFile() { - if [ -f "$1" ] ; then - rm -f $1 || echo WARNING: $1 already exists - unable to remove old copy - fi - cat << EOF > $1 -# jmxremote.password -EOF -} - - -# Check we are run from jtreg -if [ -z "${TESTCLASSES}" ]; then - echo "Test is designed to be run from jtreg only" - exit 0 -fi - - -# Test not suitable for Windows as chmod may not be able to -# security the password file. - -os=`uname -s` -if [ "$os" != "Linux" -a "$os" != "SunOS" ]; then - echo "Test not designed to run on this operating system, skipping..." - exit 0 -fi - - -# Create configuration file and dummy password file - -LIBDIR=${TESTCLASSES}/lib -CONFIG=${LIBDIR}/management.properties -PASSWD=${LIBDIR}/jmxremote.password -rm -f ${CONFIG} -rm -f ${PASSWD} -mkdir ${LIBDIR} 2>&1 -createJavaFile ${TESTCLASSES} Null -createConfigFile ${CONFIG} ${PASSWD} -createPasswordFile ${PASSWD} - -# Compile test - -${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d ${TESTCLASSES} ${TESTCLASSES}/Null.java - - -JAVA=${TESTJAVA}/bin/java -CLASSPATH=${TESTCLASSES} -export CLASSPATH - -failures=0 - -mp=-Dcom.sun.management.config.file=${CONFIG} -pp=-Dcom.sun.management.jmxremote.port=4888 - -go() { - echo '' - sh -xc "$JAVA ${TESTVMOPTS} $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -# Test 1 - password file is secure - VM should start -chmod 700 ${PASSWD} -sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Null" 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -# Test 2 - password file is not secure - VM should fail to start -chmod o+rx ${PASSWD} -sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Null" 2>&1 -if [ $? = 0 ]; then failures=`expr $failures + 1`; fi - -# Reset the file permissions on the generated password file -chmod 777 ${PASSWD} - -# -# Results -# -echo '' -if [ $failures -gt 0 ]; - then echo "$failures test(s) failed"; - else echo "All test(s) passed"; fi -exit $failures - - - diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java index adda49b7fca..cc5f00983fa 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java +++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java @@ -27,7 +27,6 @@ import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.net.BindException; -import java.net.ServerSocket; import java.rmi.server.ExportException; import java.util.Properties; @@ -43,8 +42,6 @@ import javax.management.*; import sun.management.AgentConfigurationError; -import util.TestLogger; - /** *

This class implements unit test for RMI Bootstrap. * When called with no arguments main() looks in the directory indicated @@ -71,17 +68,10 @@ import util.TestLogger; **/ public class RmiBootstrapTest { // the number of consecutive ports to test for availability - private static final int PORT_TEST_LEN = 800; + private static int MAX_GET_FREE_PORT_TRIES = 10; static TestLogger log = new TestLogger("RmiBootstrapTest"); - /** - * When launching several registries, we increment the port number - * to avoid falling into "port number already in use" problems. - **/ - static int testPort = 0; - static int basePort = 0; - /** * Default values for RMI configuration properties. **/ @@ -627,92 +617,100 @@ public class RmiBootstrapTest { * eventually cleans up by calling ConnectorBootstrap.terminate(). * @return null if the test succeeds, an error message otherwise. **/ - private String testConfiguration(File file,int port) throws BindException { + private String testConfiguration(File file) throws IOException, InterruptedException { - final String path; - try { - path=(file==null)?null:file.getCanonicalPath(); - } catch(IOException x) { - final String err = "Failed to test configuration " + file + - ": " + x; - log.trace("testConfiguration",err); - log.debug("testConfiguration",x); - return err; - } - final String config = (path==null)?"Default config file":path; - - System.out.println("***"); - System.out.println("*** Testing configuration (port=" + port + "): " - + path); - System.out.println("***"); - - System.setProperty("com.sun.management.jmxremote.port", - Integer.toString(port)); - if (path != null) - System.setProperty("com.sun.management.config.file", path); - else - System.getProperties().remove("com.sun.management.config.file"); - - log.trace("testConfiguration","com.sun.management.jmxremote.port="+port); - if (path != null && log.isDebugOn()) - log.trace("testConfiguration", - "com.sun.management.config.file="+path); - - checkSslConfiguration(); - - final JMXConnectorServer cs; - try { - cs = ConnectorBootstrap.initialize(); - } catch (AgentConfigurationError x) { - if (x.getCause() instanceof ExportException) { - if (x.getCause().getCause() instanceof BindException) { - throw (BindException)x.getCause().getCause(); + for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; i++) { + try { + int port = jdk.testlibrary.Utils.getFreePort(); + final String path; + try { + path=(file==null)?null:file.getCanonicalPath(); + } catch(IOException x) { + final String err = "Failed to test configuration " + file + + ": " + x; + log.trace("testConfiguration",err); + log.debug("testConfiguration",x); + return err; } - } - final String err = "Failed to initialize connector:" + - "\n\tcom.sun.management.jmxremote.port=" + port + - ((path!=null)?"\n\tcom.sun.management.config.file="+path: - "\n\t"+config) + - "\n\tError is: " + x; - log.trace("testConfiguration",err); - log.debug("testConfiguration",x); - return err; - } catch (Exception x) { - log.debug("testConfiguration",x); - return x.toString(); - } + final String config = (path==null)?"Default config file":path; - try { - JMXServiceURL url = - new JMXServiceURL("rmi",null,0,"/jndi/rmi://localhost:"+ - port+"/jmxrmi"); + System.out.println("***"); + System.out.println("*** Testing configuration (port=" + port + "): " + + path); + System.out.println("***"); - try { - testCommunication(url); - } catch (Exception x) { - final String err = "Failed to connect to agent {url="+url+ - "}: " + x; - log.trace("testConfiguration",err); - log.debug("testConfiguration",x); - return err; - } - } catch (Exception x) { - final String err = "Failed to test configuration "+config+ - ": "+x; - log.trace("testConfiguration",err); - log.debug("testConfiguration",x); - return err; - } finally { - try { - cs.stop(); - } catch (Exception x) { - final String err = "Failed to terminate: "+x; - log.trace("testConfiguration",err); - log.debug("testConfiguration",x); + System.setProperty("com.sun.management.jmxremote.port", + Integer.toString(port)); + if (path != null) + System.setProperty("com.sun.management.config.file", path); + else + System.getProperties().remove("com.sun.management.config.file"); + + log.trace("testConfiguration","com.sun.management.jmxremote.port="+port); + if (path != null && log.isDebugOn()) + log.trace("testConfiguration", + "com.sun.management.config.file="+path); + + checkSslConfiguration(); + + final JMXConnectorServer cs; + try { + cs = ConnectorBootstrap.initialize(); + } catch (AgentConfigurationError x) { + if (x.getCause() instanceof ExportException) { + if (x.getCause().getCause() instanceof BindException) { + throw (BindException)x.getCause().getCause(); + } + } + final String err = "Failed to initialize connector:" + + "\n\tcom.sun.management.jmxremote.port=" + port + + ((path!=null)?"\n\tcom.sun.management.config.file="+path: + "\n\t"+config) + + "\n\tError is: " + x; + log.trace("testConfiguration",err); + log.debug("testConfiguration",x); + return err; + } catch (Exception x) { + log.debug("testConfiguration",x); + return x.toString(); + } + + try { + JMXServiceURL url = + new JMXServiceURL("rmi",null,0,"/jndi/rmi://localhost:"+ + port+"/jmxrmi"); + + try { + testCommunication(url); + } catch (Exception x) { + final String err = "Failed to connect to agent {url="+url+ + "}: " + x; + log.trace("testConfiguration",err); + log.debug("testConfiguration",x); + return err; + } + } catch (Exception x) { + final String err = "Failed to test configuration "+config+ + ": "+x; + log.trace("testConfiguration",err); + log.debug("testConfiguration",x); + return err; + } finally { + try { + cs.stop(); + } catch (Exception x) { + final String err = "Failed to terminate: "+x; + log.trace("testConfiguration",err); + log.debug("testConfiguration",x); + } + } + System.out.println("Configuration " + config + " successfully tested"); + return null; + } catch(BindException ex) { } } - System.out.println("Configuration " + config + " successfully tested"); - return null; + System.err.println("Cannot find a free port after " + MAX_GET_FREE_PORT_TRIES + " tries"); + return "Failed: cannot find a free port after " + MAX_GET_FREE_PORT_TRIES + " tries"; } /** @@ -720,23 +718,16 @@ public class RmiBootstrapTest { * The test is assumed to have succeeded if the bootstrap fails. * @return null if the test succeeds, an error message otherwise. **/ - private String testConfigurationKo(File conf,int port) { + private String testConfigurationKo(File conf) throws InterruptedException, IOException { String errStr = null; - for (int i = 0; i < PORT_TEST_LEN; i++) { - try { - errStr = testConfiguration(conf,port+testPort++); - break; - } catch (BindException e) { - // port conflict; try another port - } - } + errStr = testConfiguration(conf); if (errStr == null) { return "Configuration " + conf + " should have failed!"; } System.out.println("Configuration " + conf + " failed as expected"); - log.debug("runko","Error was: " + errStr); + log.debug("runko", "Error was: " + errStr); return null; } @@ -747,26 +738,16 @@ public class RmiBootstrapTest { * *ko.properties: bootstrap or connection should fail. * @return null if the test succeeds, an error message otherwise. **/ - private String testConfigurationFile(String fileName) { + private String testConfigurationFile(String fileName) throws InterruptedException, IOException { File file = new File(fileName); - final String portStr = System.getProperty("rmi.port",null); - final int port = portStr != null ? - Integer.parseInt(portStr) : basePort; if (fileName.endsWith("ok.properties")) { String errStr = null; - for (int i = 0; i < PORT_TEST_LEN; i++) { - try { - errStr = testConfiguration(file,port+testPort++); - return errStr; - } catch (BindException e) { - // port conflict; try another port - } - } - return "Can not locate available port"; + errStr = testConfiguration(file); + return errStr; } if (fileName.endsWith("ko.properties")) { - return testConfigurationKo(file,port+testPort++); + return testConfigurationKo(file); } return fileName + ": test file suffix must be one of [ko|ok].properties"; @@ -777,17 +758,14 @@ public class RmiBootstrapTest { * (see findConfigurationFilesKo() and testConfigurationKo()) * @throws RuntimeException if the test fails. **/ - public void runko() { - final String portStr = System.getProperty("rmi.port",null); - final int port = portStr != null ? - Integer.parseInt(portStr) : basePort; + public void runko() throws InterruptedException, IOException { final File[] conf = findConfigurationFilesKo(); if ((conf == null)||(conf.length == 0)) throw new RuntimeException("No configuration found"); String errStr; for (int i=0;i model = new HashMap<>(); - public static void main(String args[]) throws Exception { + private RmiRegistrySslTest() { + try { + MAX_GET_FREE_PORT_TRIES = Integer.parseInt(System.getProperty("test.getfreeport.max.tries", "10")); + } catch (NumberFormatException ex) { + } + } - System.out.println("RmiRegistry lookup..."); + private void initPort() { + try { + port = Utils.getFreePort(); + } catch (Exception e) { + } + model.put("${getFreePort}", new Integer(port)); + } - String testID = System.getProperty("testID"); + private void initTestEnvironment() throws IOException { + initPort(); - if ("Test1".equals(testID)) { + Files.deleteIfExists(rmiRegistryFile); + Files.deleteIfExists(rmiRegistrySslFile); + libDir.toFile().mkdir(); + createFileByTemplate(rmiRegistryTemplate, rmiRegistryFile, model); + createFileByTemplate(rmiRegistrySslTemplate, rmiRegistrySslFile, model); + } + + public static void createFileByTemplate(Path template, Path out, Map model) throws IOException { + if (Files.exists(out) && Files.isRegularFile(out)) { try { - Registry registry = LocateRegistry.getRegistry(4444); - String[] list = registry.list(); - if ("jmxrmi".equals(list[0])) { - System.out.println(ok); - } else { - System.out.println(ko); - throw new IllegalArgumentException(ko); - } - } catch (Exception e) { - System.out.println(koException); - e.printStackTrace(System.out); - throw e; + Files.delete(out); + } catch (Exception ex) { + System.out.println("WARNING: " + out.toFile().getAbsolutePath() + " already exists - unable to remove old copy"); + ex.printStackTrace(); } } - if ("Test2".equals(testID)) { - try { - Registry registry = LocateRegistry.getRegistry(4444); - String[] list = registry.list(); - throw new IllegalArgumentException(ko2); - } catch (Exception e) { - System.out.println(okException); - e.printStackTrace(System.out); - return; - } - } - - if ("Test3".equals(testID)) { - try { - Registry registry = LocateRegistry.getRegistry( - null, 4444, new SslRMIClientSocketFactory()); - String[] list = registry.list(); - if ("jmxrmi".equals(list[0])) { - System.out.println(ok); - } else { - System.out.println(ko); - throw new IllegalArgumentException(ko); + try (BufferedReader br = Files.newBufferedReader(template, Charset.defaultCharset()); + BufferedWriter bw = Files.newBufferedWriter(out, Charset.defaultCharset())) { + String line; + while ((line = br.readLine()) != null) { + if (model != null) { + for (Map.Entry macro : model.entrySet()) { + line = line.replaceAll(Pattern.quote(macro.getKey()), macro.getValue().toString()); + } } - } catch (Exception e) { - System.out.println(koException); - e.printStackTrace(System.out); - throw e; + + bw.write(line, 0, line.length()); + bw.newLine(); } } } + + public void runTest(String[] args) throws Exception { + + test1(); + test2(); + test3(); + + if (failures == 0) { + System.out.println("All test(s) passed"); + } else { + throw new Error(String.format("%d test(s) failed", failures)); + } + } + + private void test1() throws Exception { + System.out.println("-------------------------------------------------------------"); + System.out.println(getClass().getName() + " : Non SSL RMIRegistry - Non SSL Lookup"); + System.out.println("-------------------------------------------------------------"); + + int res = doTest("-DtestID=Test1", + "-Dcom.sun.management.config.file=" + rmiRegistryFile.toFile().getAbsolutePath()); + + if (res != 0) { + ++failures; + } + } + + private void test2() throws Exception { + System.out.println("-------------------------------------------------------------"); + System.out.println(getClass().getName() + " : SSL RMIRegistry - Non SSL Lookup"); + System.out.println("-------------------------------------------------------------"); + + int res = doTest("-DtestID=Test2", + "-Dcom.sun.management.config.file=" + rmiRegistrySslFile.toFile().getAbsolutePath()); + + if (res != 0) { + ++failures; + } + } + + private void test3() throws Exception { + + System.out.println("-------------------------------------------------------------"); + System.out.println(getClass().getName() + " : SSL RMIRegistry - SSL Lookup"); + System.out.println("-------------------------------------------------------------"); + + int res = doTest("-DtestID=Test3", + "-Djavax.net.ssl.keyStore=" + FS.getPath(TEST_SRC, "ssl", "keystore").toFile().getAbsolutePath(), + "-Djavax.net.ssl.keyStorePassword=password", + "-Djavax.net.ssl.trustStore=" + FS.getPath(TEST_SRC, "ssl", "truststore").toFile().getAbsolutePath(), + "-Djavax.net.ssl.trustStorePassword=trustword", + "-Dcom.sun.management.config.file=" + rmiRegistrySslFile.toFile().getAbsolutePath()); + + if (res != 0) { + ++failures; + } + } + + private int doTest(String... args) throws Exception { + + for (int i = 0; i < MAX_GET_FREE_PORT_TRIES; ++i) { + + initTestEnvironment(); + + List command = new ArrayList<>(); + command.addAll(Utils.getVmOptions()); + command.add("-Dtest.src=" + TEST_SRC); + command.add("-Dtest.rmi.port=" + port); + command.addAll(Arrays.asList(args)); + command.add("-cp"); + command.add(TEST_CLASS_PATH); + command.add(className); + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(command.toArray(new String[command.size()])); + + Process p = processBuilder.start(); + OutputAnalyzer output = new OutputAnalyzer(p); + + System.out.println("test output:"); + System.out.println(output.getOutput()); + + if (!output.getOutput().contains("Exception thrown by the agent : " + + "java.rmi.server.ExportException: Port already in use")) { + return p.exitValue(); + } + } + throw new Error("Cannot find free port"); + } + + public static void main(String[] args) throws Exception { + RmiRegistrySslTest test = new RmiRegistrySslTest(); + + test.runTest(args); + } } diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh deleted file mode 100644 index 2e5d752e7b2..00000000000 --- a/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please 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 6228231 -# @summary Test that RMI registry uses SSL. -# @author Luis-Miguel Alventosa -# @run clean RmiRegistrySslTest -# @run build RmiRegistrySslTest -# @run shell/timeout=300 RmiRegistrySslTest.sh - -echo ------------------------------------------------------------- -echo `basename $0 .sh` : Non SSL RMIRegistry - Non SSL Lookup -echo ------------------------------------------------------------- - -${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} \ - -Dtest.src=${TESTSRC} \ - -DtestID=Test1 \ - -Dcom.sun.management.config.file=${TESTSRC}/rmiregistry.properties \ - RmiRegistrySslTest || exit $? - -echo ------------------------------------------------------------- -echo `basename $0 .sh` : SSL RMIRegistry - Non SSL Lookup -echo ------------------------------------------------------------- - -${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} \ - -Dtest.src=${TESTSRC} \ - -DtestID=Test2 \ - -Dcom.sun.management.config.file=${TESTSRC}/rmiregistryssl.properties \ - RmiRegistrySslTest || exit $? - -echo ------------------------------------------------------------- -echo `basename $0 .sh` : SSL RMIRegistry - SSL Lookup -echo ------------------------------------------------------------- - -${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES} \ - -Dtest.src=${TESTSRC} \ - -DtestID=Test3 \ - -Djavax.net.ssl.keyStore=${TESTSRC}/ssl/keystore \ - -Djavax.net.ssl.keyStorePassword=password \ - -Djavax.net.ssl.trustStore=${TESTSRC}/ssl/truststore \ - -Djavax.net.ssl.trustStorePassword=trustword \ - -Dcom.sun.management.config.file=${TESTSRC}/rmiregistryssl.properties \ - RmiRegistrySslTest || exit $? diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTestApp.java b/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTestApp.java new file mode 100644 index 00000000000..33e008636b9 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTestApp.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import javax.rmi.ssl.SslRMIClientSocketFactory; +import jdk.testlibrary.Utils; + + +public class RmiRegistrySslTestApp { + + static final String ok = "OK: Found jmxrmi entry in RMIRegistry!"; + static final String ko = "KO: Did not find jmxrmi entry in RMIRegistry!"; + static final String ko2 = "KO: Did not get expected exception!"; + static final String okException = "OK: Got expected exception!"; + static final String koException = "KO: Got unexpected exception!"; + + public static void main(String args[]) throws Exception { + + System.out.println("RmiRegistry lookup..."); + + String testID = System.getProperty("testID"); + int port = Integer.parseInt(System.getProperty("test.rmi.port")); + + if ("Test1".equals(testID)) { + try { + Registry registry = LocateRegistry.getRegistry(port); + String[] list = registry.list(); + if ("jmxrmi".equals(list[0])) { + System.out.println(ok); + } else { + System.out.println(ko); + throw new IllegalArgumentException(ko); + } + } catch (Exception e) { + System.out.println(koException); + e.printStackTrace(System.out); + throw e; + } + } + + if ("Test2".equals(testID)) { + try { + Registry registry = LocateRegistry.getRegistry(port); + String[] list = registry.list(); + throw new IllegalArgumentException(ko2); + } catch (Exception e) { + System.out.println(okException); + e.printStackTrace(System.out); + return; + } + } + + if ("Test3".equals(testID)) { + try { + Registry registry = LocateRegistry.getRegistry( + null, port, new SslRMIClientSocketFactory()); + String[] list = registry.list(); + if ("jmxrmi".equals(list[0])) { + System.out.println(ok); + } else { + System.out.println(ko); + throw new IllegalArgumentException(ko); + } + } catch (Exception e) { + System.out.println(koException); + e.printStackTrace(System.out); + throw e; + } + } + } +} diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh index e20422e508a..7a786a357ad 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh +++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh @@ -26,7 +26,11 @@ # @bug 6528083 # @summary Test RMI Bootstrap with SSL # -# @build TestLogger RmiBootstrapTest Utils +# @library /lib/testlibrary +# @build jdk.testlibrary.Utils +# @build TestLogger +# @build Utils +# @build RmiBootstrapTest # @run shell/timeout=300 RmiSslBootstrapTest.sh # Define the Java class test name diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java index 663e46cced0..6296e7e2607 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java +++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java @@ -45,8 +45,6 @@ import javax.management.*; import sun.management.AgentConfigurationError; -import util.TestLogger; - /** *

This class implements unit test for RMI Bootstrap. * When called with no arguments main() looks in the directory indicated diff --git a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java new file mode 100644 index 00000000000..149e9c4ef38 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; + +/** + * @test + * @library /lib/testlibrary + * @bug 6557093 + * @bug 6557093 + * @build jdk.testlibrary.Utils + * @build jdk.testlibrary.ProcessTools + * @build jdk.testlibrary.OutputAnalyzer + * @build Dummy + * @build AbstractFilePermissionTest + * @summary Check SSL config file permission for out-of-the-box management + * @run main/timeout=300 SSLConfigFilePermissionTest + * + * @author Taras Ledkov + */ +public class SSLConfigFilePermissionTest extends AbstractFilePermissionTest { + + private final String TEST_SRC = System.getProperty("test.src"); + + private SSLConfigFilePermissionTest() { + super("jmxremote.ssl.config"); + } + + public void testSetup() throws IOException { + createFile(mgmt, + "# management.properties", + "com.sun.management.jmxremote.authenticate=false", + "com.sun.management.jmxremote.ssl.config.file=" + file2PermissionTest.toFile().getAbsolutePath()); + + createFile(file2PermissionTest, + "# management.properties", + "javax.net.ssl.keyStore = " + + FS.getPath(TEST_SRC, "ssl", "keystore").toFile().getAbsolutePath(), + "javax.net.ssl.keyStorePassword = password"); + } + + public static void main(String[] args) throws Exception { + SSLConfigFilePermissionTest test = new SSLConfigFilePermissionTest(); + + test.runTest(args); + } +} + + diff --git a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh deleted file mode 100644 index 022aa2a4d26..00000000000 --- a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please 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 6557093 -# @summary Check SSL config file permission for out-of-the-box management -# -# @run shell SSLConfigFilePermissionTest.sh - -createJavaFile() -{ - cat << EOF > $1/$2.java - class $2 { - public static void main(String[] args) { - System.out.println("Inside main method..."); - } - } -EOF -} - -createManagementConfigFile() { - cat << EOF > $1 -# management.properties -com.sun.management.jmxremote.authenticate=false -com.sun.management.jmxremote.ssl.config.file=$2 -EOF -} - -createSSLConfigFile() { - if [ -f "$1" ] ; then - rm -f $1 || echo WARNING: $1 already exists - unable to remove old copy - fi - cat << EOF > $1 -javax.net.ssl.keyStore=$2 -javax.net.ssl.keyStorePassword=password -EOF -} - -# Check we are run from jtreg -if [ -z "${TESTCLASSES}" ]; then - echo "Test is designed to be run from jtreg only" - exit 0 -fi - -# Test not suitable for Windows as chmod may not be able to -# security the password file. - -os=`uname -s` -if [ "$os" != "Linux" -a "$os" != "SunOS" ]; then - echo "Test not designed to run on this operating system, skipping..." - exit 0 -fi - -# Create management and SSL configuration files - -LIBDIR=${TESTCLASSES}/lib -MGMT=${LIBDIR}/management.properties -SSL=${LIBDIR}/jmxremote.ssl.config -rm -f ${MGMT} -rm -f ${SSL} -mkdir ${LIBDIR} 2>&1 -createJavaFile ${TESTCLASSES} Dummy -createManagementConfigFile ${MGMT} ${SSL} -createSSLConfigFile ${SSL} ${TESTSRC}/ssl/keystore - -# Compile test - -${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d ${TESTCLASSES} ${TESTCLASSES}/Dummy.java - -JAVA=${TESTJAVA}/bin/java -CLASSPATH=${TESTCLASSES} -export CLASSPATH - -failures=0 - -mp=-Dcom.sun.management.config.file=${MGMT} -pp=-Dcom.sun.management.jmxremote.port=4999 - -go() { - echo '' - sh -xc "$JAVA ${TESTVMOPTS} $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -# Test 1 - SSL config file is secure - VM should start -chmod 700 ${SSL} -sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Dummy" 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -# Test 2 - SSL config file is not secure - VM should fail to start -chmod o+rx ${SSL} -sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Dummy" 2>&1 -if [ $? = 0 ]; then failures=`expr $failures + 1`; fi - -# Reset the file permissions on the generated SSL config file -chmod 777 ${SSL} - -# -# Results -# -echo '' -if [ $failures -gt 0 ]; - then echo "$failures test(s) failed"; - else echo "All test(s) passed"; fi -exit $failures diff --git a/jdk/test/sun/management/jmxremote/bootstrap/TestLogger.java b/jdk/test/sun/management/jmxremote/bootstrap/TestLogger.java index 3858f4f9384..adec3aa8b22 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/TestLogger.java +++ b/jdk/test/sun/management/jmxremote/bootstrap/TestLogger.java @@ -20,7 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package util; import java.util.logging.Logger; import java.util.logging.Level; diff --git a/jdk/test/sun/management/jmxremote/bootstrap/rmiregistry.properties b/jdk/test/sun/management/jmxremote/bootstrap/rmiregistry.properties index 718ebd13a5d..7b3f2f6b9ae 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/rmiregistry.properties +++ b/jdk/test/sun/management/jmxremote/bootstrap/rmiregistry.properties @@ -24,7 +24,7 @@ # ################ Management Agent Port ######################### # # For setting the JMX RMI agent port use the following line -com.sun.management.jmxremote.port=4444 +com.sun.management.jmxremote.port=${getFreePort} # # For setting the SNMP agent port use the following line # com.sun.management.snmp.port= diff --git a/jdk/test/sun/management/jmxremote/bootstrap/rmiregistryssl.properties b/jdk/test/sun/management/jmxremote/bootstrap/rmiregistryssl.properties index eb336ee0af5..3b3b81c350e 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/rmiregistryssl.properties +++ b/jdk/test/sun/management/jmxremote/bootstrap/rmiregistryssl.properties @@ -24,7 +24,7 @@ # ################ Management Agent Port ######################### # # For setting the JMX RMI agent port use the following line -com.sun.management.jmxremote.port=4444 +com.sun.management.jmxremote.port=${getFreePort} # # For setting the SNMP agent port use the following line # com.sun.management.snmp.port= From a6354ef8f2ff5358eeb7eb2c5d691857764baa47 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 28 Feb 2014 13:35:32 +0100 Subject: [PATCH 216/265] 8035904: Solaris fastdebug builds are failing Reviewed-by: tbell --- common/autoconf/configure | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/autoconf/configure b/common/autoconf/configure index 588a31cc42c..730f51a0c0f 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -127,10 +127,11 @@ function shell_quote() { if [[ -n "$1" ]]; then # Uses only shell-safe characters? No quoting needed. # '=' is a zsh meta-character, but only in word-initial position. - if [[ "$1" =~ ^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.:,%/+=_-]+$ && ! "$1" =~ ^= ]]; then + if echo "$1" | grep -qE '^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.:,%/+=_-]+$' \ + && ! echo "$1" | grep -qE '^='; then quoted="$1" else - if [[ "$1" =~ [\'!] ]]; then + if echo "$1" | grep -qE "[\'!]"; then # csh does history expansion within single quotes, but not # when backslash-escaped! local quoted_quote="'\\''" quoted_exclam="'\\!'" From e2ab209b1204a67e0ecc19c1a0d7d504e614d6fc Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Fri, 28 Feb 2014 15:39:15 +0100 Subject: [PATCH 217/265] 8035668: [test] Check that jstat does not cause problems when monitored application exits before jstat finishes its work Reviewed-by: sla --- jdk/test/sun/tools/jstat/JStatInterval.java | 126 ++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 jdk/test/sun/tools/jstat/JStatInterval.java diff --git a/jdk/test/sun/tools/jstat/JStatInterval.java b/jdk/test/sun/tools/jstat/JStatInterval.java new file mode 100644 index 00000000000..0d39df23e10 --- /dev/null +++ b/jdk/test/sun/tools/jstat/JStatInterval.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8035668 + * @library /lib/testlibrary + * @summary Test checks case when target application finishes execution and jstat didn't complete work. + jstat is started with interval = 100 (jstat -compiler 100) and monitored application finishes + after 500ms. This shouldn't cause crash or hang in target application or in jstat. + * @build jdk.testlibrary.ProcessTools jdk.testlibrary.JDKToolLauncher + * @build JStatInterval + * @run main JStatInterval + */ + +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.JDKToolLauncher; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class JStatInterval { + private static final String PID = "PID"; + private static final String READY = "READY"; + private static final String ERROR = "!ERROR"; + + public static class Application { + public static void main(String[] args) { + try { + System.out.println(PID + ":" + ProcessTools.getProcessId()); + System.out.println(READY); + System.out.flush(); + int exitCode = System.in.read(); + Thread.sleep(500); + System.exit(exitCode); + } catch (Exception e) { + System.out.println(ERROR); + System.out.flush(); + throw new Error(e); + } + } + } + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-cp", + System.getProperty("test.class.path"), + "-XX:+UsePerfData", + Application.class.getName() + ); + AtomicInteger pid = new AtomicInteger(-1); + AtomicBoolean error = new AtomicBoolean(false); + Process app = ProcessTools.startProcess( + "application", + pb, + line -> { + if (line.startsWith(PID)) { + pid.set(Integer.parseInt(line.split("\\:")[1])); + } else if (line.equals(READY)) { + return true; + } else if (line.equals(ERROR)) { + error.set(true); + return true; + } + return false; + }, + 10, + TimeUnit.SECONDS + ); + if (error.get()) { + throw new Error("Unable to start the monitored application."); + } + + String pidStr = String.valueOf(pid.get()); + JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jstat"); + l.addToolArg("-compiler"); + l.addToolArg(pidStr); + l.addToolArg("100"); + + ProcessBuilder jstatDef = new ProcessBuilder(l.getCommand()); + Process jstat = ProcessTools.startProcess( + "jstat", + jstatDef, + line -> { + if (line.trim().toLowerCase().startsWith("compiled")) { + return true; + } + return false; + }, + 10, + TimeUnit.SECONDS + ); + + app.getOutputStream().write(0); + app.getOutputStream().flush(); + + if (app.waitFor() != 0) { + throw new Error("Error detected upon exiting the monitored application with active jstat"); + } + if (jstat.waitFor() != 0) { + throw new Error("Error detected in jstat when monitored application has exited prematurely"); + } + } +} From 3eb1d7659f6c55e78226a6ef68ed4e6f1836ab14 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Fri, 28 Feb 2014 17:14:08 +0100 Subject: [PATCH 218/265] 8035949: Remove unused macro USE_SELECT and clean up Unix version of net_util_md.{c,h} Reviewed-by: chegar, alanb --- jdk/src/aix/native/java/net/aix_close.c | 8 --- .../native/java/net/Inet4AddressImpl.c | 4 +- .../native/java/net/Inet6AddressImpl.c | 2 +- .../solaris/native/java/net/PlainSocketImpl.c | 57 +++------------ jdk/src/solaris/native/java/net/bsd_close.c | 8 --- jdk/src/solaris/native/java/net/linux_close.c | 8 --- jdk/src/solaris/native/java/net/net_util_md.c | 69 +++++-------------- jdk/src/solaris/native/java/net/net_util_md.h | 64 +++++------------ .../solaris/native/java/net/solaris_close.c | 5 -- 9 files changed, 49 insertions(+), 176 deletions(-) diff --git a/jdk/src/aix/native/java/net/aix_close.c b/jdk/src/aix/native/java/net/aix_close.c index e6aca129b7c..d23d5cfebcf 100644 --- a/jdk/src/aix/native/java/net/aix_close.c +++ b/jdk/src/aix/native/java/net/aix_close.c @@ -374,17 +374,9 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) { BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) ); } -#ifndef USE_SELECT int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); } -#else -int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, - select(s, readfds, writefds, exceptfds, timeout) ); -} -#endif /* * Wrapper for poll(s, timeout). diff --git a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c index 29bb069daac..e07b2f578f4 100644 --- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c @@ -164,7 +164,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, if (error) { /* report error */ - ThrowUnknownHostExceptionWithGaiError(env, hostname, error); + NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } else { @@ -416,7 +416,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, if (error) { /* report error */ - ThrowUnknownHostExceptionWithGaiError(env, hostname, error); + NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } else { diff --git a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c index b65d9b08f94..7e348b6b79c 100644 --- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c @@ -305,7 +305,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, if (error) { /* report error */ - ThrowUnknownHostExceptionWithGaiError(env, hostname, error); + NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } else { diff --git a/jdk/src/solaris/native/java/net/PlainSocketImpl.c b/jdk/src/solaris/native/java/net/PlainSocketImpl.c index d4f0a693d4e..e1c349576cf 100644 --- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c +++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c @@ -27,7 +27,7 @@ #include #include #include -#if defined(__linux__) && !defined(USE_SELECT) +#if defined(__linux__) #include #endif #include /* Defines TCP_NODELAY, needed for 2.6 */ @@ -309,26 +309,11 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this, * See 6343810. */ while (1) { -#ifndef USE_SELECT - { - struct pollfd pfd; - pfd.fd = fd; - pfd.events = POLLOUT; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLOUT; - connect_rv = NET_Poll(&pfd, 1, -1); - } -#else - { - fd_set wr, ex; - - FD_ZERO(&wr); - FD_SET(fd, &wr); - FD_ZERO(&ex); - FD_SET(fd, &ex); - - connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0); - } -#endif + connect_rv = NET_Poll(&pfd, 1, -1); if (connect_rv == -1) { if (errno == EINTR) { @@ -381,38 +366,18 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this, /* * Wait for the connection to be established or a - * timeout occurs. poll/select needs to handle EINTR in + * timeout occurs. poll needs to handle EINTR in * case lwp sig handler redirects any process signals to * this thread. */ while (1) { jlong newTime; -#ifndef USE_SELECT - { - struct pollfd pfd; - pfd.fd = fd; - pfd.events = POLLOUT; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLOUT; - errno = 0; - connect_rv = NET_Poll(&pfd, 1, timeout); - } -#else - { - fd_set wr, ex; - struct timeval t; - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&wr); - FD_SET(fd, &wr); - FD_ZERO(&ex); - FD_SET(fd, &ex); - - errno = 0; - connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t); - } -#endif + errno = 0; + connect_rv = NET_Poll(&pfd, 1, timeout); if (connect_rv >= 0) { break; diff --git a/jdk/src/solaris/native/java/net/bsd_close.c b/jdk/src/solaris/native/java/net/bsd_close.c index a414cf2b762..67856b0ba34 100644 --- a/jdk/src/solaris/native/java/net/bsd_close.c +++ b/jdk/src/solaris/native/java/net/bsd_close.c @@ -322,17 +322,9 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) { BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) ); } -#ifndef USE_SELECT int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); } -#else -int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, - select(s, readfds, writefds, exceptfds, timeout) ); -} -#endif /* * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399. diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c index 85557942c16..8472fa792d3 100644 --- a/jdk/src/solaris/native/java/net/linux_close.c +++ b/jdk/src/solaris/native/java/net/linux_close.c @@ -304,17 +304,9 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) { BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) ); } -#ifndef USE_SELECT int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); } -#else -int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, - select(s, readfds, writefds, exceptfds, timeout) ); -} -#endif /* * Wrapper for poll(s, timeout). diff --git a/jdk/src/solaris/native/java/net/net_util_md.c b/jdk/src/solaris/native/java/net/net_util_md.c index cfd3ec8d4f8..e463d46276f 100644 --- a/jdk/src/solaris/native/java/net/net_util_md.c +++ b/jdk/src/solaris/native/java/net/net_util_md.c @@ -75,13 +75,6 @@ #include "java_net_SocketOptions.h" -/* needed from libsocket on Solaris 8 */ - -getaddrinfo_f getaddrinfo_ptr = NULL; -freeaddrinfo_f freeaddrinfo_ptr = NULL; -gai_strerror_f gai_strerror_ptr = NULL; -getnameinfo_f getnameinfo_ptr = NULL; - /* * EXCLBIND socket options only on Solaris */ @@ -446,15 +439,14 @@ jint IPv6_supported() } #endif /* DONT_ENABLE_IPV6 */ -void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, - const char* hostname, - int gai_error) +void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, + const char* hostname, + int gai_error) { int size; char *buf; const char *format = "%s: %s"; - const char *error_string = - (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error); + const char *error_string = gai_strerror(gai_error); if (error_string == NULL) error_string = "unknown error"; @@ -1614,7 +1606,7 @@ NET_Bind(int fd, struct sockaddr *him, int len) } /** - * Wrapper for select/poll with timeout on a single file descriptor. + * Wrapper for poll with timeout on a single file descriptor. * * flags (defined in net_util_md.h can be any combination of * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT. @@ -1633,47 +1625,18 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) while (1) { jlong newTime; -#ifndef USE_SELECT - { - struct pollfd pfd; - pfd.fd = fd; - pfd.events = 0; - if (flags & NET_WAIT_READ) - pfd.events |= POLLIN; - if (flags & NET_WAIT_WRITE) - pfd.events |= POLLOUT; - if (flags & NET_WAIT_CONNECT) - pfd.events |= POLLOUT; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = 0; + if (flags & NET_WAIT_READ) + pfd.events |= POLLIN; + if (flags & NET_WAIT_WRITE) + pfd.events |= POLLOUT; + if (flags & NET_WAIT_CONNECT) + pfd.events |= POLLOUT; - errno = 0; - read_rv = NET_Poll(&pfd, 1, timeout); - } -#else - { - fd_set rd, wr, ex; - struct timeval t; - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - if (flags & NET_WAIT_READ) { - FD_SET(fd, &rd); - } - if (flags & NET_WAIT_WRITE) { - FD_SET(fd, &wr); - } - if (flags & NET_WAIT_CONNECT) { - FD_SET(fd, &wr); - FD_SET(fd, &ex); - } - - errno = 0; - read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t); - } -#endif + errno = 0; + read_rv = NET_Poll(&pfd, 1, timeout); newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); diff --git a/jdk/src/solaris/native/java/net/net_util_md.h b/jdk/src/solaris/native/java/net/net_util_md.h index 07bc99d45cf..e7150da6018 100644 --- a/jdk/src/solaris/native/java/net/net_util_md.h +++ b/jdk/src/solaris/native/java/net/net_util_md.h @@ -32,9 +32,7 @@ #include #include -#ifndef USE_SELECT #include -#endif int NET_Timeout(int s, long timeout); int NET_Read(int s, void* buf, size_t len); @@ -43,54 +41,26 @@ int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, int NET_ReadV(int s, const struct iovec * vector, int count); int NET_Send(int s, void *msg, int len, unsigned int flags); int NET_SendTo(int s, const void *msg, int len, unsigned int - flags, const struct sockaddr *to, int tolen); + flags, const struct sockaddr *to, int tolen); int NET_Writev(int s, const struct iovec * vector, int count); int NET_Connect(int s, struct sockaddr *addr, int addrlen); int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen); int NET_SocketClose(int s); int NET_Dup2(int oldfd, int newfd); -#ifdef USE_SELECT -extern int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout); -#else -extern int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout); -#endif - +int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout); int NET_SocketAvailable(int s, jint *pbytes); -#if defined(__linux__) && defined(AF_INET6) -int getDefaultIPv6Interface(struct in6_addr *target_addr); -#endif +void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, + const char* hostname, + int gai_error); +void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, + const char *defaultDetail); -#ifdef __solaris__ -extern int net_getParam(char *driver, char *param); -#endif +#define NET_WAIT_READ 0x01 +#define NET_WAIT_WRITE 0x02 +#define NET_WAIT_CONNECT 0x04 -/* needed from libsocket on Solaris 8 */ - -typedef int (*getaddrinfo_f)(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res); - -typedef void (*freeaddrinfo_f)(struct addrinfo *); - -typedef const char * (*gai_strerror_f)(int ecode); - -typedef int (*getnameinfo_f)(const struct sockaddr *, size_t, - char *, size_t, char *, size_t, int); - -extern getaddrinfo_f getaddrinfo_ptr; -extern freeaddrinfo_f freeaddrinfo_ptr; -extern getnameinfo_f getnameinfo_ptr; - -void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, - const char* hostname, - int gai_error); - -#define NET_WAIT_READ 0x01 -#define NET_WAIT_WRITE 0x02 -#define NET_WAIT_CONNECT 0x04 - -extern jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); +jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); /************************************************************************ * Macros and constants @@ -127,12 +97,16 @@ extern jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); /************************************************************************ * Utilities */ + #ifdef __linux__ -extern int kernelIsV24(); +int kernelIsV24(); +#ifdef AF_INET6 +int getDefaultIPv6Interface(struct in6_addr *target_addr); +#endif #endif -void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, - const char *defaultDetail); - +#ifdef __solaris__ +int net_getParam(char *driver, char *param); +#endif #endif /* NET_UTILS_MD_H */ diff --git a/jdk/src/solaris/native/java/net/solaris_close.c b/jdk/src/solaris/native/java/net/solaris_close.c index 8b07d95d4f7..0cf7b5c96fc 100644 --- a/jdk/src/solaris/native/java/net/solaris_close.c +++ b/jdk/src/solaris/native/java/net/solaris_close.c @@ -86,11 +86,6 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout)); } -int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - RESTARTABLE_RETURN_INT(select(s, readfds, writefds, exceptfds, timeout)); -} - int NET_Timeout(int s, long timeout) { int result; struct timeval t; From 23afad496990d7e65cb0657bab2fc25f28e1ab6b Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Fri, 28 Feb 2014 09:38:10 -0800 Subject: [PATCH 219/265] 8036004: Incorrect license header for a test class Reviewed-by: alanb --- .../xml/jaxp/transform/8004476/TestBase.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/jdk/test/javax/xml/jaxp/transform/8004476/TestBase.java b/jdk/test/javax/xml/jaxp/transform/8004476/TestBase.java index 4b6ea705e17..11333faa3ca 100644 --- a/jdk/test/javax/xml/jaxp/transform/8004476/TestBase.java +++ b/jdk/test/javax/xml/jaxp/transform/8004476/TestBase.java @@ -1,7 +1,26 @@ /* * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.security.Policy; /** From c92ff7d5e70aebfb577d1912843c573b96a63631 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Fri, 28 Feb 2014 10:27:54 -0800 Subject: [PATCH 220/265] 6835233: Fedora 9 jdk regression test failed: java/lang/instrument/ParallelTransformerLoader.sh Remove @ignore from ParallelTransformerLoader.sh Reviewed-by: alanb, sla, smarks --- jdk/test/java/lang/instrument/ParallelTransformerLoader.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh b/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh index 586869cf945..0801f07e222 100644 --- a/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh +++ b/jdk/test/java/lang/instrument/ParallelTransformerLoader.sh @@ -23,7 +23,6 @@ # @test # @bug 5088398 -# @ignore until bug 6835233 dealt with # @summary Test parallel class loading by parallel transformers. # @author Daniel D. Daugherty as modified from the code of Daryl Puryear @ Wily # From e112d0032d60fc1aa6c42f5bac284c1a91ed94e2 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Fri, 28 Feb 2014 13:36:46 -0500 Subject: [PATCH 221/265] 8035889: jdk testlibrary - add printing of values of failed assertions Extend and cleanup testlibrary Reviewed-by: mchung, sla --- jdk/test/lib/testlibrary/AssertsTest.java | 43 ++- .../testlibrary/jdk/testlibrary/Asserts.java | 339 ++++++++++++------ 2 files changed, 277 insertions(+), 105 deletions(-) diff --git a/jdk/test/lib/testlibrary/AssertsTest.java b/jdk/test/lib/testlibrary/AssertsTest.java index e59a2521bfe..a9efe219465 100644 --- a/jdk/test/lib/testlibrary/AssertsTest.java +++ b/jdk/test/lib/testlibrary/AssertsTest.java @@ -25,7 +25,6 @@ import static jdk.testlibrary.Asserts.*; /* @test * @summary Tests the different assertions in the Assert class - * @library /testlibrary */ public class AssertsTest { private static class Foo implements Comparable { @@ -37,6 +36,9 @@ public class AssertsTest { public int compareTo(Foo f) { return new Integer(id).compareTo(new Integer(f.id)); } + public String toString() { + return "Foo(" + Integer.toString(id) + ")"; + } } public static void main(String[] args) throws Exception { @@ -50,6 +52,7 @@ public class AssertsTest { testNotNull(); testTrue(); testFalse(); + testFail(); } private static void testLessThan() throws Exception { @@ -72,7 +75,7 @@ public class AssertsTest { private static void testEquals() throws Exception { expectPass(Assertion.EQ, 1, 1); - expectPass(Assertion.EQ, null, null); + expectPass(Assertion.EQ, (Comparable)null, (Comparable)null); Foo f1 = new Foo(1); expectPass(Assertion.EQ, f1, f1); @@ -109,13 +112,13 @@ public class AssertsTest { Foo f2 = new Foo(1); expectPass(Assertion.NE, f1, f2); - expectFail(Assertion.NE, null, null); + expectFail(Assertion.NE, (Comparable)null, (Comparable)null); expectFail(Assertion.NE, f1, f1); expectFail(Assertion.NE, 1, 1); } private static void testNull() throws Exception { - expectPass(Assertion.NULL, null); + expectPass(Assertion.NULL, (Comparable)null); expectFail(Assertion.NULL, 1); } @@ -123,7 +126,7 @@ public class AssertsTest { private static void testNotNull() throws Exception { expectPass(Assertion.NOTNULL, 1); - expectFail(Assertion.NOTNULL, null); + expectFail(Assertion.NOTNULL, (Comparable)null); } private static void testTrue() throws Exception { @@ -138,6 +141,36 @@ public class AssertsTest { expectFail(Assertion.FALSE, true); } + private static void testFail() throws Exception { + try { + fail(); + } catch (RuntimeException re) { + assertEquals("fail", re.getMessage()); + } + + try { + fail("Failure"); + } catch (RuntimeException re) { + assertEquals("Failure", re.getMessage()); + } + + Exception e = new Exception("the cause"); + try { + fail("Fail w/ cause", e); + } catch (RuntimeException re) { + assertEquals("Fail w/ cause", re.getMessage()); + assertEquals(e, re.getCause(), "Cause mismatch"); + } + + try { + fail(1, 2, "Different", "vs"); + } catch (RuntimeException re) { + assertEquals("Different <1> vs <2>", re.getMessage()); + } + } + + + private static > void expectPass(Assertion assertion, T ... args) throws Exception { Assertion.run(assertion, args); diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java index d5e13610406..573fde935f9 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java @@ -23,16 +23,17 @@ package jdk.testlibrary; +import java.util.Objects; + /** * Asserts that can be used for verifying assumptions in tests. * - * An assertion will throw a {@link RuntimeException} if the assertion isn't - * valid. All the asserts can be imported into a test by using a static - * import: + * An assertion will throw a {@link RuntimeException} if the assertion isn't true. + * All the asserts can be imported into a test by using a static import: * *

  * {@code
- * import static com.oracle.java.testlibrary.Asserts.*;
+ * import static jdk.testlibrary.Asserts.*;
  * }
  *
  * Always provide a message describing the assumption if the line number of the
@@ -45,111 +46,147 @@ package jdk.testlibrary;
 public class Asserts {
 
     /**
-     * Shorthand for {@link #assertLessThan(T, T)}.
+     * Shorthand for {@link #assertLessThan(Comparable, Comparable)}.
      *
-     * @see #assertLessThan(T, T)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertLessThan(Comparable, Comparable)
      */
     public static > void assertLT(T lhs, T rhs) {
         assertLessThan(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertLessThan(T, T, String)}.
+     * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}.
      *
-     * @see #assertLessThan(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertLessThan(Comparable, Comparable, String)
      */
     public static > void assertLT(T lhs, T rhs, String msg) {
         assertLessThan(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertLessThan(T, T, String)} with a default message.
+     * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message.
      *
-     * @see #assertLessThan(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertLessThan(Comparable, Comparable, String)
      */
     public static > void assertLessThan(T lhs, T rhs) {
-        String msg = "Expected that " + format(lhs) + " < " + format(rhs);
-        assertLessThan(lhs, rhs, msg);
+        assertLessThan(lhs, rhs, null);
     }
 
     /**
      * Asserts that {@code lhs} is less than {@code rhs}.
      *
+     * @param  a type
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static >void assertLessThan(T lhs, T rhs, String msg) {
-        assertTrue(compare(lhs, rhs, msg) < 0, msg);
+        if (!(compare(lhs, rhs, msg) < 0)) {
+            msg = Objects.toString(msg, "assertLessThan")
+                    + ": expected that " + Objects.toString(lhs)
+                    + " < " + Objects.toString(rhs);
+            fail(msg);
+        }
     }
 
     /**
-     * Shorthand for {@link #assertLessThanOrEqual(T, T)}.
+     * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}.
      *
-     * @see #assertLessThanOrEqual(T, T)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertLessThanOrEqual(Comparable, Comparable)
      */
     public static > void assertLTE(T lhs, T rhs) {
         assertLessThanOrEqual(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertLessThanOrEqual(T, T, String)}.
+     * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}.
      *
-     * @see #assertLessThanOrEqual(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertLessThanOrEqual(Comparable, Comparable, String)
      */
     public static > void assertLTE(T lhs, T rhs, String msg) {
         assertLessThanOrEqual(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertLessThanOrEqual(T, T, String)} with a default message.
+     * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message.
      *
-     * @see #assertLessThanOrEqual(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertLessThanOrEqual(Comparable, Comparable, String)
      */
     public static > void assertLessThanOrEqual(T lhs, T rhs) {
-        String msg = "Expected that " + format(lhs) + " <= " + format(rhs);
-        assertLessThanOrEqual(lhs, rhs, msg);
+        assertLessThanOrEqual(lhs, rhs, null);
     }
 
     /**
      * Asserts that {@code lhs} is less than or equal to {@code rhs}.
      *
+     * @param  a type
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static > void assertLessThanOrEqual(T lhs, T rhs, String msg) {
-        assertTrue(compare(lhs, rhs, msg) <= 0, msg);
+        if (!(compare(lhs, rhs, msg) <= 0)) {
+            msg = Objects.toString(msg, "assertLessThanOrEqual")
+                    + ": expected that " + Objects.toString(lhs)
+                    + " <= " + Objects.toString(rhs);
+            fail(msg);
+        }
     }
 
     /**
-     * Shorthand for {@link #assertEquals(T, T)}.
+     * Shorthand for {@link #assertEquals(Object, Object)}.
      *
-     * @see #assertEquals(T, T)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertEquals(Object, Object)
      */
     public static void assertEQ(Object lhs, Object rhs) {
         assertEquals(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertEquals(T, T, String)}.
+     * Shorthand for {@link #assertEquals(Object, Object, String)}.
      *
-     * @see #assertEquals(T, T, String)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertEquals(Object, Object, String)
      */
     public static void assertEQ(Object lhs, Object rhs, String msg) {
         assertEquals(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertEquals(T, T, String)} with a default message.
+     * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
      *
-     * @see #assertEquals(T, T, String)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertEquals(Object, Object, String)
      */
     public static void assertEquals(Object lhs, Object rhs) {
-        String msg = "Expected " + format(lhs) + " to equal " + format(rhs);
-        assertEquals(lhs, rhs, msg);
+        assertEquals(lhs, rhs, null);
     }
 
     /**
@@ -157,125 +194,160 @@ public class Asserts {
      *
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertEquals(Object lhs, Object rhs, String msg) {
-        if (lhs == null) {
-            if (rhs != null) {
-                error(msg);
-            }
-        } else {
-            assertTrue(lhs.equals(rhs), msg);
+        if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) {
+            msg = Objects.toString(msg, "assertEquals")
+                    + ": expected " + Objects.toString(lhs)
+                    + " to equal " + Objects.toString(rhs);
+            fail(msg);
         }
     }
 
     /**
-     * Shorthand for {@link #assertGreaterThanOrEqual(T, T)}.
+     * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}.
      *
-     * @see #assertGreaterThanOrEqual(T, T)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertGreaterThanOrEqual(Comparable, Comparable)
      */
     public static > void assertGTE(T lhs, T rhs) {
         assertGreaterThanOrEqual(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertGreaterThanOrEqual(T, T, String)}.
+     * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}.
      *
-     * @see #assertGreaterThanOrEqual(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
      */
     public static > void assertGTE(T lhs, T rhs, String msg) {
         assertGreaterThanOrEqual(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertGreaterThanOrEqual(T, T, String)} with a default message.
+     * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message.
      *
-     * @see #assertGreaterThanOrEqual(T, T, String)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
      */
     public static > void assertGreaterThanOrEqual(T lhs, T rhs) {
-        String msg = "Expected that " + format(lhs) + " >= " + format(rhs);
-        assertGreaterThanOrEqual(lhs, rhs, msg);
+        assertGreaterThanOrEqual(lhs, rhs, null);
     }
 
     /**
      * Asserts that {@code lhs} is greater than or equal to {@code rhs}.
      *
+     * @param  a type
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static > void assertGreaterThanOrEqual(T lhs, T rhs, String msg) {
-        assertTrue(compare(lhs, rhs, msg) >= 0, msg);
+        if (!(compare(lhs, rhs, msg) >= 0)) {
+            msg = Objects.toString(msg, "assertGreaterThanOrEqual")
+                    + ": expected " + Objects.toString(lhs)
+                    + " >= " + Objects.toString(rhs);
+            fail(msg);
+        }
     }
 
     /**
-     * Shorthand for {@link #assertGreaterThan(T, T)}.
+     * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}.
      *
-     * @see #assertGreaterThan(T, T)
+     * @param  a type
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertGreaterThan(Comparable, Comparable)
      */
     public static > void assertGT(T lhs, T rhs) {
         assertGreaterThan(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertGreaterThan(T, T, String)}.
+     * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}.
      *
-     * @see #assertGreaterThan(T, T, String)
+     * @param  a type
+     * @param lhs the left hand value
+     * @param rhs the right hand value
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertGreaterThan(Comparable, Comparable, String)
      */
     public static > void assertGT(T lhs, T rhs, String msg) {
         assertGreaterThan(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertGreaterThan(T, T, String)} with a default message.
+     * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message.
      *
-     * @see #assertGreaterThan(T, T, String)
+     * @param  a type
+     * @param lhs the left hand value
+     * @param rhs the right hand value
+     * @see #assertGreaterThan(Comparable, Comparable, String)
      */
     public static > void assertGreaterThan(T lhs, T rhs) {
-        String msg = "Expected that " + format(lhs) + " > " + format(rhs);
-        assertGreaterThan(lhs, rhs, msg);
+        assertGreaterThan(lhs, rhs, null);
     }
 
     /**
      * Asserts that {@code lhs} is greater than {@code rhs}.
      *
+     * @param  a type
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static > void assertGreaterThan(T lhs, T rhs, String msg) {
-        assertTrue(compare(lhs, rhs, msg) > 0, msg);
+        if (!(compare(lhs, rhs, msg) > 0)) {
+            msg = Objects.toString(msg, "assertGreaterThan")
+                    + ": expected " + Objects.toString(lhs)
+                    + " > " + Objects.toString(rhs);
+            fail(msg);
+        }
     }
 
     /**
-     * Shorthand for {@link #assertNotEquals(T, T)}.
+     * Shorthand for {@link #assertNotEquals(Object, Object)}.
      *
-     * @see #assertNotEquals(T, T)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertNotEquals(Object, Object)
      */
     public static void assertNE(Object lhs, Object rhs) {
         assertNotEquals(lhs, rhs);
     }
 
     /**
-     * Shorthand for {@link #assertNotEquals(T, T, String)}.
+     * Shorthand for {@link #assertNotEquals(Object, Object, String)}.
      *
-     * @see #assertNotEquals(T, T, String)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @see #assertNotEquals(Object, Object, String)
      */
     public static void assertNE(Object lhs, Object rhs, String msg) {
         assertNotEquals(lhs, rhs, msg);
     }
 
     /**
-     * Calls {@link #assertNotEquals(T, T, String)} with a default message.
+     * Calls {@link #assertNotEquals(Object, Object, String)} with a default message.
      *
-     * @see #assertNotEquals(T, T, String)
+     * @param lhs The left hand side of the comparison.
+     * @param rhs The right hand side of the comparison.
+     * @see #assertNotEquals(Object, Object, String)
      */
     public static void assertNotEquals(Object lhs, Object rhs) {
-        String msg = "Expected " + format(lhs) + " to not equal " + format(rhs);
-        assertNotEquals(lhs, rhs, msg);
+        assertNotEquals(lhs, rhs, null);
     }
 
     /**
@@ -283,34 +355,34 @@ public class Asserts {
      *
      * @param lhs The left hand side of the comparison.
      * @param rhs The right hand side of the comparison.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertNotEquals(Object lhs, Object rhs, String msg) {
-        if (lhs == null) {
-            if (rhs == null) {
-                error(msg);
-            }
-        } else {
-            assertFalse(lhs.equals(rhs), msg);
+        if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) {
+            msg = Objects.toString(msg, "assertNotEquals")
+                    + ": expected " + Objects.toString(lhs)
+                    + " to not equal " + Objects.toString(rhs);
+            fail(msg);
         }
     }
 
     /**
      * Calls {@link #assertNull(Object, String)} with a default message.
      *
+     * @param o The reference assumed to be null.
      * @see #assertNull(Object, String)
      */
     public static void assertNull(Object o) {
-        assertNull(o, "Expected " + format(o) + " to be null");
+        assertNull(o, null);
     }
 
     /**
      * Asserts that {@code o} is null.
      *
      * @param o The reference assumed to be null.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertNull(Object o, String msg) {
         assertEquals(o, null, msg);
@@ -319,18 +391,19 @@ public class Asserts {
     /**
      * Calls {@link #assertNotNull(Object, String)} with a default message.
      *
+     * @param o The reference assumed not to be null,
      * @see #assertNotNull(Object, String)
      */
     public static void assertNotNull(Object o) {
-        assertNotNull(o, "Expected non null reference");
+        assertNotNull(o, null);
     }
 
     /**
      * Asserts that {@code o} is not null.
      *
      * @param o The reference assumed not to be null,
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertNotNull(Object o, String msg) {
         assertNotEquals(o, null, msg);
@@ -339,57 +412,123 @@ public class Asserts {
     /**
      * Calls {@link #assertFalse(boolean, String)} with a default message.
      *
+     * @param value The value assumed to be false.
      * @see #assertFalse(boolean, String)
      */
     public static void assertFalse(boolean value) {
-        assertFalse(value, "Expected value to be false");
+        assertFalse(value, null);
     }
 
     /**
      * Asserts that {@code value} is {@code false}.
      *
      * @param value The value assumed to be false.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertFalse(boolean value, String msg) {
-        assertTrue(!value, msg);
+        if (value) {
+            msg = Objects.toString(msg, "assertFalse")
+                    + ": expected false, was true";
+            fail(msg);
+        }
     }
 
     /**
      * Calls {@link #assertTrue(boolean, String)} with a default message.
      *
+     * @param value The value assumed to be true.
      * @see #assertTrue(boolean, String)
      */
     public static void assertTrue(boolean value) {
-        assertTrue(value, "Expected value to be true");
+        assertTrue(value, null);
     }
 
     /**
      * Asserts that {@code value} is {@code true}.
      *
      * @param value The value assumed to be true.
-     * @param msg A description of the assumption.
-     * @throws RuntimeException if the assertion isn't valid.
+     * @param msg A description of the assumption; {@code null} for a default message.
+     * @throws RuntimeException if the assertion is not true.
      */
     public static void assertTrue(boolean value, String msg) {
         if (!value) {
-            error(msg);
+            msg = Objects.toString(msg, "assertTrue")
+                    + ": expected true, was false";
+            fail(msg);
         }
     }
 
     private static > int compare(T lhs, T rhs, String msg) {
-        assertNotNull(lhs, msg);
-        assertNotNull(rhs, msg);
+        if (lhs == null || rhs == null) {
+            fail(lhs, rhs, msg + ": values must be non-null:", ",");
+        }
         return lhs.compareTo(rhs);
     }
 
-    private static String format(Object o) {
-        return o == null? "null" : o.toString();
+    /**
+     * Returns a string formatted with a message and expected and actual values.
+     * @param lhs the actual value
+     * @param rhs  the expected value
+     * @param message the actual value
+     * @param relation the asserted relationship between lhs and rhs
+     * @return a formatted string
+     */
+    public static String format(Object lhs, Object rhs, String message, String relation) {
+        StringBuilder sb = new StringBuilder(80);
+        if (message != null) {
+            sb.append(message);
+            sb.append(' ');
+        }
+        sb.append("<");
+        sb.append(Objects.toString(lhs));
+        sb.append("> ");
+        sb.append(Objects.toString(relation, ","));
+        sb.append(" <");
+        sb.append(Objects.toString(rhs));
+        sb.append(">");
+        return sb.toString();
     }
 
-    private static void error(String msg) {
-        throw new RuntimeException(msg);
+    /**
+     * Fail reports a failure with message fail.
+     *
+     * @throws RuntimeException always
+     */
+    public static void fail() {
+        fail("fail");
+    }
+
+    /**
+     * Fail reports a failure with a message.
+     * @param message for the failure
+     * @throws RuntimeException always
+     */
+    public static void fail(String message) {
+        throw new RuntimeException(message);
+    }
+
+    /**
+     * Fail reports a failure with a formatted message.
+     *
+     * @param lhs the actual value
+     * @param rhs the expected value
+     * @param message to be format before the expected and actual values
+     * @param relation the asserted relationship between lhs and rhs
+     * @throws RuntimeException always
+     */
+    public static void fail(Object lhs, Object rhs, String message, String relation) {
+        throw new RuntimeException(format(lhs, rhs, message, relation));
+    }
+
+    /**
+     * Fail reports a failure with a message and a cause.
+     * @param message to be format before the expected and actual values
+     * @param cause the exception that caused this failure
+     * @throws RuntimeException always
+     */
+    public static void fail(String message, Throwable cause) {
+        throw new RuntimeException(message, cause);
     }
 
 }

From 81b6eb6a69f8253aa4c2256244149dc106e2d25f Mon Sep 17 00:00:00 2001
From: Roger Riggs 
Date: Fri, 28 Feb 2014 17:01:12 -0500
Subject: [PATCH 222/265] 8035106: Typo in java.time.format.Parsed error
 message

Reviewed-by: lancea
---
 jdk/src/share/classes/java/time/format/Parsed.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/jdk/src/share/classes/java/time/format/Parsed.java b/jdk/src/share/classes/java/time/format/Parsed.java
index 71961003e23..f9878bbb580 100644
--- a/jdk/src/share/classes/java/time/format/Parsed.java
+++ b/jdk/src/share/classes/java/time/format/Parsed.java
@@ -289,7 +289,7 @@ final class Parsed implements TemporalAccessor {
                             changedCount++;
                             continue outer;  // have to restart to avoid concurrent modification
                         }
-                        throw new DateTimeException("Method resolveFields() can only return ChronoZonedDateTime," +
+                        throw new DateTimeException("Method resolve() can only return ChronoZonedDateTime, " +
                                 "ChronoLocalDateTime, ChronoLocalDate or LocalTime");
                     } else if (fieldValues.containsKey(targetField) == false) {
                         changedCount++;

From 856f5c58234b90a24250778a2c216e67e6a812fb Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov 
Date: Sat, 1 Mar 2014 02:05:53 +0400
Subject: [PATCH 223/265] 8027827: Improve performance of catchException
 combinator 8034120: MethodHandles.catchException doesn't handle
 VarargsCollector right

Reviewed-by: lagergren, psandoz, jrose
---
 .../java/lang/invoke/BoundMethodHandle.java   |  14 +
 .../lang/invoke/InvokerBytecodeGenerator.java | 160 ++++++++-
 .../classes/java/lang/invoke/LambdaForm.java  |  56 +++
 .../java/lang/invoke/MethodHandleImpl.java    | 325 ++++++++----------
 .../java/lang/invoke/MethodTypeForm.java      |   3 +-
 .../MethodHandles/TestCatchException.java     |  35 ++
 6 files changed, 393 insertions(+), 200 deletions(-)

diff --git a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
index 288cd2d2a5b..91960b2d73f 100644
--- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -861,4 +861,18 @@ import jdk.internal.org.objectweb.asm.Type;
      * All subclasses must provide such a value describing their type signature.
      */
     static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
+
+    private static final SpeciesData[] SPECIES_DATA_CACHE = new SpeciesData[5];
+    private static SpeciesData checkCache(int size, String types) {
+        int idx = size - 1;
+        SpeciesData data = SPECIES_DATA_CACHE[idx];
+        if (data != null)  return data;
+        SPECIES_DATA_CACHE[idx] = data = getSpeciesData(types);
+        return data;
+    }
+    static SpeciesData speciesData_L()     { return checkCache(1, "L"); }
+    static SpeciesData speciesData_LL()    { return checkCache(2, "LL"); }
+    static SpeciesData speciesData_LLL()   { return checkCache(3, "LLL"); }
+    static SpeciesData speciesData_LLLL()  { return checkCache(4, "LLLL"); }
+    static SpeciesData speciesData_LLLLL() { return checkCache(5, "LLLLL"); }
 }
diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index bb873b10c5a..8ce18cdc062 100644
--- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -27,7 +27,6 @@ package java.lang.invoke;
 
 import sun.invoke.util.VerifyAccess;
 import java.lang.invoke.LambdaForm.Name;
-import java.lang.invoke.MethodHandles.Lookup;
 
 import sun.invoke.util.Wrapper;
 
@@ -39,8 +38,6 @@ import jdk.internal.org.objectweb.asm.*;
 import java.lang.reflect.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyType;
 
 /**
@@ -51,7 +48,6 @@ import sun.invoke.util.VerifyType;
 class InvokerBytecodeGenerator {
     /** Define class names for convenience. */
     private static final String MH      = "java/lang/invoke/MethodHandle";
-    private static final String BMH     = "java/lang/invoke/BoundMethodHandle";
     private static final String LF      = "java/lang/invoke/LambdaForm";
     private static final String LFN     = "java/lang/invoke/LambdaForm$Name";
     private static final String CLS     = "java/lang/Class";
@@ -511,17 +507,22 @@ class InvokerBytecodeGenerator {
             Name name = lambdaForm.names[i];
             MemberName member = name.function.member();
 
-            if (isSelectAlternative(member)) {
-                // selectAlternative idiom
-                // FIXME: make sure this idiom is really present!
+            if (isSelectAlternative(i)) {
                 emitSelectAlternative(name, lambdaForm.names[i + 1]);
                 i++;  // skip MH.invokeBasic of the selectAlternative result
+            } else if (isGuardWithCatch(i)) {
+                emitGuardWithCatch(i);
+                i = i+2; // Jump to the end of GWC idiom
             } else if (isStaticallyInvocable(member)) {
                 emitStaticInvoke(member, name);
             } else {
                 emitInvoke(name);
             }
 
+            // Update cached form name's info in case an intrinsic spanning multiple names was encountered.
+            name = lambdaForm.names[i];
+            member = name.function.member();
+
             // store the result from evaluating to the target name in a local if required
             // (if this is the last value, i.e., the one that is going to be returned,
             // avoid store/load/return and just return)
@@ -674,12 +675,66 @@ class InvokerBytecodeGenerator {
     }
 
     /**
-     * Check if MemberName is a call to MethodHandleImpl.selectAlternative.
+     * Check if MemberName is a call to a method named {@code name} in class {@code declaredClass}.
      */
-    private boolean isSelectAlternative(MemberName member) {
+    private boolean memberRefersTo(MemberName member, Class declaringClass, String name) {
         return member != null &&
-               member.getDeclaringClass() == MethodHandleImpl.class &&
-               member.getName().equals("selectAlternative");
+               member.getDeclaringClass() == declaringClass &&
+               member.getName().equals(name);
+    }
+    private boolean nameRefersTo(Name name, Class declaringClass, String methodName) {
+        return name.function != null &&
+               memberRefersTo(name.function.member(), declaringClass, methodName);
+    }
+
+    /**
+     * Check if MemberName is a call to MethodHandle.invokeBasic.
+     */
+    private boolean isInvokeBasic(Name name) {
+        if (name.function == null)
+            return false;
+        if (name.arguments.length < 1)
+            return false;  // must have MH argument
+        MemberName member = name.function.member();
+        return memberRefersTo(member, MethodHandle.class, "invokeBasic") &&
+               !member.isPublic() && !member.isStatic();
+    }
+
+    /**
+     * Check if i-th name is a call to MethodHandleImpl.selectAlternative.
+     */
+    private boolean isSelectAlternative(int pos) {
+        // selectAlternative idiom:
+        //   t_{n}:L=MethodHandleImpl.selectAlternative(...)
+        //   t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
+        if (pos+1 >= lambdaForm.names.length)  return false;
+        Name name0 = lambdaForm.names[pos];
+        Name name1 = lambdaForm.names[pos+1];
+        return nameRefersTo(name0, MethodHandleImpl.class, "selectAlternative") &&
+               isInvokeBasic(name1) &&
+               name1.lastUseIndex(name0) == 0 &&        // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
+               lambdaForm.lastUseIndex(name0) == pos+1; // t_{n} is local: used only in t_{n+1}
+    }
+
+    /**
+     * Check if i-th name is a start of GuardWithCatch idiom.
+     */
+    private boolean isGuardWithCatch(int pos) {
+        // GuardWithCatch idiom:
+        //   t_{n}:L=MethodHandle.invokeBasic(...)
+        //   t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n});
+        //   t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1})
+        if (pos+2 >= lambdaForm.names.length)  return false;
+        Name name0 = lambdaForm.names[pos];
+        Name name1 = lambdaForm.names[pos+1];
+        Name name2 = lambdaForm.names[pos+2];
+        return nameRefersTo(name1, MethodHandleImpl.class, "guardWithCatch") &&
+               isInvokeBasic(name0) &&
+               isInvokeBasic(name2) &&
+               name1.lastUseIndex(name0) == 3 &&          // t_{n+1}:L=MethodHandleImpl.guardWithCatch(*, *, *, t_{n});
+               lambdaForm.lastUseIndex(name0) == pos+1 && // t_{n} is local: used only in t_{n+1}
+               name2.lastUseIndex(name1) == 1 &&          // t_{n+2}:?=MethodHandle.invokeBasic(t_{n+1})
+               lambdaForm.lastUseIndex(name1) == pos+2;   // t_{n+1} is local: used only in t_{n+2}
     }
 
     /**
@@ -694,8 +749,6 @@ class InvokerBytecodeGenerator {
      * }
*/ private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { - MethodType type = selectAlternativeName.function.methodType(); - Name receiver = (Name) invokeBasicName.arguments[0]; Label L_fallback = new Label(); @@ -709,7 +762,6 @@ class InvokerBytecodeGenerator { mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback); // invoke selectAlternativeName.arguments[1] - MethodHandle target = (MethodHandle) selectAlternativeName.arguments[1]; emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitInvoke(invokeBasicName); @@ -721,7 +773,6 @@ class InvokerBytecodeGenerator { mv.visitLabel(L_fallback); // invoke selectAlternativeName.arguments[2] - MethodHandle fallback = (MethodHandle) selectAlternativeName.arguments[2]; emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot emitInvoke(invokeBasicName); @@ -730,6 +781,85 @@ class InvokerBytecodeGenerator { mv.visitLabel(L_done); } + /** + * Emit bytecode for the guardWithCatch idiom. + * + * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithCatch): + *
{@code
+      *  guardWithCatch=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{
+      *    t8:L=MethodHandle.invokeBasic(a4:L,a6:L,a7:L);
+      *    t9:L=MethodHandleImpl.guardWithCatch(a1:L,a2:L,a3:L,t8:L);
+      *   t10:I=MethodHandle.invokeBasic(a5:L,t9:L);t10:I}
+      * }
+ * + * It is compiled into bytecode equivalent of the following code: + *
{@code
+      *  try {
+      *      return a1.invokeBasic(a6, a7);
+      *  } catch (Throwable e) {
+      *      if (!a2.isInstance(e)) throw e;
+      *      return a3.invokeBasic(ex, a6, a7);
+      *  }}
+      */
+    private void emitGuardWithCatch(int pos) {
+        Name args    = lambdaForm.names[pos];
+        Name invoker = lambdaForm.names[pos+1];
+        Name result  = lambdaForm.names[pos+2];
+
+        Label L_startBlock = new Label();
+        Label L_endBlock = new Label();
+        Label L_handler = new Label();
+        Label L_done = new Label();
+
+        Class returnType = result.function.resolvedHandle.type().returnType();
+        MethodType type = args.function.resolvedHandle.type()
+                              .dropParameterTypes(0,1)
+                              .changeReturnType(returnType);
+
+        mv.visitTryCatchBlock(L_startBlock, L_endBlock, L_handler, "java/lang/Throwable");
+
+        // Normal case
+        mv.visitLabel(L_startBlock);
+        // load target
+        emitPushArgument(invoker, 0);
+        emitPushArguments(args, 1); // skip 1st argument: method handle
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
+        mv.visitLabel(L_endBlock);
+        mv.visitJumpInsn(Opcodes.GOTO, L_done);
+
+        // Exceptional case
+        mv.visitLabel(L_handler);
+
+        // Check exception's type
+        mv.visitInsn(Opcodes.DUP);
+        // load exception class
+        emitPushArgument(invoker, 1);
+        mv.visitInsn(Opcodes.SWAP);
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "isInstance", "(Ljava/lang/Object;)Z", false);
+        Label L_rethrow = new Label();
+        mv.visitJumpInsn(Opcodes.IFEQ, L_rethrow);
+
+        // Invoke catcher
+        // load catcher
+        emitPushArgument(invoker, 2);
+        mv.visitInsn(Opcodes.SWAP);
+        emitPushArguments(args, 1); // skip 1st argument: method handle
+        MethodType catcherType = type.insertParameterTypes(0, Throwable.class);
+        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", catcherType.basicType().toMethodDescriptorString(), false);
+        mv.visitJumpInsn(Opcodes.GOTO, L_done);
+
+        mv.visitLabel(L_rethrow);
+        mv.visitInsn(Opcodes.ATHROW);
+
+        mv.visitLabel(L_done);
+    }
+
+    private void emitPushArguments(Name args, int start) {
+        for (int i = start; i < args.arguments.length; i++) {
+            emitPushArgument(args, i);
+        }
+    }
+
     private void emitPushArgument(Name name, int paramIndex) {
         Object arg = name.arguments[paramIndex];
         char ptype = name.function.parameterType(paramIndex);
diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
index c3ab19f3ce5..a5e40ed5211 100644
--- a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
@@ -1465,6 +1465,33 @@ class LambdaForm {
             return false;
         }
 
+        /** Return the index of the last occurrence of n in the argument array.
+         *  Return -1 if the name is not used.
+         */
+        int lastUseIndex(Name n) {
+            if (arguments == null)  return -1;
+            for (int i = arguments.length; --i >= 0; ) {
+                if (arguments[i] == n)  return i;
+            }
+            return -1;
+        }
+
+        /** Return the number of occurrences of n in the argument array.
+         *  Return 0 if the name is not used.
+         */
+        int useCount(Name n) {
+            if (arguments == null)  return 0;
+            int count = 0;
+            for (int i = arguments.length; --i >= 0; ) {
+                if (arguments[i] == n)  ++count;
+            }
+            return count;
+        }
+
+        boolean contains(Name n) {
+            return this == n || lastUseIndex(n) >= 0;
+        }
+
         public boolean equals(Name that) {
             if (this == that)  return true;
             if (isParam())
@@ -1488,6 +1515,35 @@ class LambdaForm {
         }
     }
 
+    /** Return the index of the last name which contains n as an argument.
+     *  Return -1 if the name is not used.  Return names.length if it is the return value.
+     */
+    int lastUseIndex(Name n) {
+        int ni = n.index, nmax = names.length;
+        assert(names[ni] == n);
+        if (result == ni)  return nmax;  // live all the way beyond the end
+        for (int i = nmax; --i > ni; ) {
+            if (names[i].lastUseIndex(n) >= 0)
+                return i;
+        }
+        return -1;
+    }
+
+    /** Return the number of times n is used as an argument or return value. */
+    int useCount(Name n) {
+        int ni = n.index, nmax = names.length;
+        int end = lastUseIndex(n);
+        if (end < 0)  return 0;
+        int count = 0;
+        if (end == nmax) { count++; end--; }
+        int beg = n.index() + 1;
+        if (beg < arity)  beg = arity;
+        for (int i = beg; i <= end; i++) {
+            count += names[i].useCount(n);
+        }
+        return count;
+    }
+
     static Name argument(int which, char type) {
         int tn = ALL_TYPES.indexOf(type);
         if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
index eca236ce308..872ecddcdf8 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -27,7 +27,6 @@ package java.lang.invoke;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import sun.invoke.empty.Empty;
@@ -482,12 +481,26 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
      * Factored in an inner class to delay initialization until first usage.
      */
     private static class Lazy {
+        private static final Class MHI = MethodHandleImpl.class;
+
         static final NamedFunction NF_checkSpreadArgument;
+        static final NamedFunction NF_guardWithCatch;
+        static final NamedFunction NF_selectAlternative;
+        static final NamedFunction NF_throwException;
+
         static {
             try {
-                NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
-                        .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
+                NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
+                NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
+                                                                                 MethodHandle.class, Object[].class));
+                NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
+                                                                                 MethodHandle.class));
+                NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
+
                 NF_checkSpreadArgument.resolve();
+                NF_guardWithCatch.resolve();
+                NF_selectAlternative.resolve();
+                NF_throwException.resolve();
             } catch (ReflectiveOperationException ex) {
                 throw newInternalError(ex);
             }
@@ -548,24 +561,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
         return SimpleMethodHandle.make(srcType, form);
     }
 
+    @LambdaForm.Hidden
     static
     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
         return testResult ? target : fallback;
     }
 
-    static MethodHandle SELECT_ALTERNATIVE;
-    static MethodHandle selectAlternative() {
-        if (SELECT_ALTERNATIVE != null)  return SELECT_ALTERNATIVE;
-        try {
-            SELECT_ALTERNATIVE
-            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
-                    MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
-        } catch (ReflectiveOperationException ex) {
-            throw new RuntimeException(ex);
-        }
-        return SELECT_ALTERNATIVE;
-    }
-
     static
     MethodHandle makeGuardWithTest(MethodHandle test,
                                    MethodHandle target,
@@ -585,7 +586,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
 
         // call selectAlternative
         Object[] selectArgs = { names[arity + 1], target, fallback };
-        names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
+        names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
         targetArgs[0] = names[arity + 2];
 
         // call target or fallback
@@ -595,167 +596,137 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
         return SimpleMethodHandle.make(target.type(), form);
     }
 
-    private static class GuardWithCatch {
-        private final MethodHandle target;
-        private final Class exType;
-        private final MethodHandle catcher;
-        // FIXME: Build the control flow out of foldArguments.
-        GuardWithCatch(MethodHandle target, Class exType, MethodHandle catcher) {
-            this.target = target;
-            this.exType = exType;
-            this.catcher = catcher;
-        }
-        @LambdaForm.Hidden
-        private Object invoke_V(Object... av) throws Throwable {
-            try {
-                return target.invokeExact(av);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, av);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L0() throws Throwable {
-            try {
-                return target.invokeExact();
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L1(Object a0) throws Throwable {
-            try {
-                return target.invokeExact(a0);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L2(Object a0, Object a1) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3, a4);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3, a4);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3, a4, a5);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
-            }
-        }
-        @LambdaForm.Hidden
-        private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
-            }
-        }
-        static MethodHandle[] makeInvokes() {
-            ArrayList invokes = new ArrayList<>();
-            MethodHandles.Lookup lookup = IMPL_LOOKUP;
-            for (;;) {
-                int nargs = invokes.size();
-                String name = "invoke_L"+nargs;
-                MethodHandle invoke = null;
-                try {
-                    invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
-                } catch (ReflectiveOperationException ex) {
-                }
-                if (invoke == null)  break;
-                invokes.add(invoke);
-            }
-            assert(invokes.size() == 9);  // current number of methods
-            return invokes.toArray(new MethodHandle[0]);
-        };
-        static final MethodHandle[] INVOKES = makeInvokes();
-        // For testing use this:
-        //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
-        static final MethodHandle VARARGS_INVOKE;
-        static {
-            try {
-                VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
-            } catch (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-        }
-    }
+    /**
+     * The LambaForm shape for catchException combinator is the following:
+     * 
{@code
+     *  guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
+     *    t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
+     *    t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
+     *    t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
+     *    t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
+     *    t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
+     *    t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
+     *    t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
+     *   t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
+     * }
+ * + * argL0 and argL2 are target and catcher method handles. argL1 is exception class. + * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[] + * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()). + * + * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms + * among catchException combinators with the same basic type. + */ + private static LambdaForm makeGuardWithCatchForm(MethodType basicType) { + MethodType lambdaType = basicType.invokerType(); + LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC); + if (lform != null) { + return lform; + } + final int THIS_MH = 0; // the BMH_LLLLL + final int ARG_BASE = 1; // start of incoming arguments + final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); + + int nameCursor = ARG_LIMIT; + final int GET_TARGET = nameCursor++; + final int GET_CLASS = nameCursor++; + final int GET_CATCHER = nameCursor++; + final int GET_COLLECT_ARGS = nameCursor++; + final int GET_UNBOX_RESULT = nameCursor++; + final int BOXED_ARGS = nameCursor++; + final int TRY_CATCH = nameCursor++; + final int UNBOX_RESULT = nameCursor++; + + Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); + names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]); + names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]); + names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]); + names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]); + names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]); + + // FIXME: rework argument boxing/result unboxing logic for LF interpretation + + // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...); + MethodType collectArgsType = basicType.changeReturnType(Object.class); + MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType); + Object[] args = new Object[invokeBasic.type().parameterCount()]; + args[0] = names[GET_COLLECT_ARGS]; + System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE); + names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args); + + // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L); + Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]}; + names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs); + + // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); + MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); + Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]}; + names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs); + + lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names); + + basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform); + return lform; + } static MethodHandle makeGuardWithCatch(MethodHandle target, Class exType, MethodHandle catcher) { MethodType type = target.type(); - MethodType ctype = catcher.type(); - int nargs = type.parameterCount(); - if (nargs < GuardWithCatch.INVOKES.length) { - MethodType gtype = type.generic(); - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); - // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0) - MethodHandle gtarget = makePairwiseConvert(target, gtype, 2); - MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2); - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null) throw new InternalError(); - MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard); - return makePairwiseConvert(ginvoker, type, 2); + LambdaForm form = makeGuardWithCatchForm(type.basicType()); + + // Prepare auxiliary method handles used during LambdaForm interpreation. + // Box arguments and wrap them into Object[]: ValueConversions.array(). + MethodType varargsType = type.changeReturnType(Object[].class); + MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount()) + .asType(varargsType); + // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). + MethodHandle unboxResult; + if (type.returnType().isPrimitive()) { + unboxResult = ValueConversions.unbox(type.returnType()); } else { - target = target.asType(type.changeReturnType(Object.class)); - MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs); - MethodType catcherType = ctype.changeParameterType(0, Throwable.class) - .changeReturnType(Object.class); - catcher = catcher.asType(catcherType); - MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs); - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher); - if (gtarget == null || gcatcher == null) throw new InternalError(); - MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard); - MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false); - return makePairwiseConvert(gcollect, type, 2); + unboxResult = ValueConversions.identity(); } + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); + BoundMethodHandle mh; + try { + mh = (BoundMethodHandle) + data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher, + (Object) collectArgs, (Object) unboxResult); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + assert(mh.type() == type); + return mh; + } + + /** + * Intrinsified during LambdaForm compilation + * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}). + */ + @LambdaForm.Hidden + static Object guardWithCatch(MethodHandle target, Class exType, MethodHandle catcher, + Object... av) throws Throwable { + try { + return target.invokeWithArguments(av); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + Object[] args = prepend(t, av); + return catcher.invokeWithArguments(args); + } + } + + /** Prepend an element {@code elem} to an {@code array}. */ + private static Object[] prepend(Object elem, Object[] array) { + Object[] newArray = new Object[array.length+1]; + newArray[0] = elem; + System.arraycopy(array, 0, newArray, 1, array.length); + return newArray; } static @@ -765,23 +736,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (arity > 1) { return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1); } - return makePairwiseConvert(throwException(), type, 2); + return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2); } - static MethodHandle THROW_EXCEPTION; - static MethodHandle throwException() { - MethodHandle mh = THROW_EXCEPTION; - if (mh != null) return mh; - try { - mh - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", - MethodType.methodType(Empty.class, Throwable.class)); - } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); - } - THROW_EXCEPTION = mh; - return mh; - } static Empty throwException(T t) throws T { throw t; } static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2]; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java index 80a751cfce3..ee5e6221b11 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java @@ -76,7 +76,8 @@ final class MethodTypeForm { LF_GEN_INVOKER = 12, LF_CS_LINKER = 13, // linkToCallSite_CS LF_MH_LINKER = 14, // linkToCallSite_MH - LF_LIMIT = 15; + LF_GWC = 15, + LF_LIMIT = 16; public MethodType erasedType() { return erasedType; diff --git a/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java b/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java index 106eafc1426..8f1abfc83d8 100644 --- a/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java +++ b/jdk/test/java/lang/invoke/MethodHandles/TestCatchException.java @@ -72,10 +72,45 @@ public class TestCatchException { assertEquals(x, 17); } + + public static Object m1(Object o1, Object o2, Object o3, Object o4, Object o5, + Object o6, Object o7, Object o8, Object... tail) { + return tail; + } + + public static Object m2(Exception e, Object o1, Object o2, Object o3, Object o4, + Object o5, Object o6, Object o7, Object o8, Object... tail) { + return tail; + } + + @Test + public void testVarargsCollector() throws Throwable { + MethodType t1 = MethodType.methodType(Object.class, Object.class, Object.class, Object.class, Object.class, + Object.class, Object.class, Object.class, Object.class, Object[].class); + + MethodType t2 = t1.insertParameterTypes(0, Exception.class); + + MethodHandle target = LOOKUP.findStatic(TestCatchException.class, "m1", t1) + .asVarargsCollector(Object[].class); + + MethodHandle catcher = LOOKUP.findStatic(TestCatchException.class, "m2", t2); + + MethodHandle gwc = MethodHandles.catchException(target, Exception.class, catcher); + + Object o = new Object(); + Object[] obj1 = new Object[] { "str" }; + + Object r1 = target.invokeExact(o, o, o, o, o, o, o, o, obj1); + Object r2 = gwc.invokeExact(o, o, o, o, o, o, o, o, obj1); + assertEquals(r1, obj1); + assertEquals(r2, obj1); + } + public static void main(String[] args) throws Throwable { TestCatchException test = new TestCatchException(); test.testNoThrowPath(); test.testThrowPath(); + test.testVarargsCollector(); System.out.println("TEST PASSED"); } } From 255307847f43b5a684849dab4b82fa4d088e704d Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Sat, 1 Mar 2014 02:07:30 +0400 Subject: [PATCH 224/265] 8033666: Make sure @ForceInline is everywhere it needs to be in sun.misc and java.lang.invoke Reviewed-by: twisti, jrose --- .../lang/invoke/InvokerBytecodeGenerator.java | 4 ++- .../java/lang/invoke/MethodHandleImpl.java | 26 ++++++++++++++++++- .../sun/invoke/util/ValueConversions.java | 23 ++++------------ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 8ce18cdc062..837ef0484e6 100644 --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -48,6 +48,7 @@ import sun.invoke.util.VerifyType; class InvokerBytecodeGenerator { /** Define class names for convenience. */ private static final String MH = "java/lang/invoke/MethodHandle"; + private static final String MHI = "java/lang/invoke/MethodHandleImpl"; private static final String LF = "java/lang/invoke/LambdaForm"; private static final String LFN = "java/lang/invoke/LambdaForm$Name"; private static final String CLS = "java/lang/Class"; @@ -57,6 +58,7 @@ class InvokerBytecodeGenerator { private static final String LF_SIG = "L" + LF + ";"; private static final String LFN_SIG = "L" + LFN + ";"; private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; + private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ private static final String superName = LF; @@ -433,7 +435,7 @@ class InvokerBytecodeGenerator { mv.visitLdcInsn(constantPlaceholder(pclass)); mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG, false); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); if (pclass.isArray()) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 872ecddcdf8..05bfc88bf61 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -253,7 +253,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Note: Do not check for a class hierarchy relation // between src and dst. In all cases a 'null' argument // will pass the cast conversion. - fn = ValueConversions.cast(dst); + fn = ValueConversions.cast(dst, Lazy.MH_castReference); } } Name conv = new Name(fn, names[INARG_BASE + i]); @@ -293,6 +293,25 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return SimpleMethodHandle.make(srcType, form); } + /** + * Identity function, with reference cast. + * @param t an arbitrary reference type + * @param x an arbitrary reference value + * @return the same value x + */ + @ForceInline + @SuppressWarnings("unchecked") + static T castReference(Class t, U x) { + // inlined Class.cast because we can't ForceInline it + if (x != null && !t.isInstance(x)) + throw newClassCastException(t, x); + return (T) x; + } + + private static ClassCastException newClassCastException(Class t, Object obj) { + return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); + } + static MethodHandle makeReferenceIdentity(Class refType) { MethodType lambdaType = MethodType.genericMethodType(1).invokerType(); Name[] names = arguments(1, lambdaType); @@ -488,6 +507,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static final NamedFunction NF_selectAlternative; static final NamedFunction NF_throwException; + static final MethodHandle MH_castReference; + static { try { NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); @@ -501,6 +522,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; NF_guardWithCatch.resolve(); NF_selectAlternative.resolve(); NF_throwException.resolve(); + + MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class); + MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } diff --git a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java index bf0f13d4ef2..e3095fce2d7 100644 --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java @@ -443,20 +443,6 @@ public class ValueConversions { return x; } - /** - * Identity function, with reference cast. - * @param t an arbitrary reference type - * @param x an arbitrary reference value - * @return the same value x - */ - @SuppressWarnings("unchecked") - static T castReference(Class t, U x) { - // inlined Class.cast because we can't ForceInline it - if (x != null && !t.isInstance(x)) - throw newClassCastException(t, x); - return (T) x; - } - private static ClassCastException newClassCastException(Class t, Object obj) { return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); } @@ -466,12 +452,10 @@ public class ValueConversions { static { try { MethodType idType = MethodType.genericMethodType(1); - MethodType castType = idType.insertParameterTypes(0, Class.class); MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); - //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); - CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType); + CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); @@ -509,6 +493,9 @@ public class ValueConversions { * and returns it as the given type. */ public static MethodHandle cast(Class type) { + return cast(type, CAST_REFERENCE); + } + public static MethodHandle cast(Class type, MethodHandle castReference) { if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); MethodHandle mh; Wrapper wrap = null; @@ -519,7 +506,7 @@ public class ValueConversions { mh = cache.get(wrap); if (mh != null) return mh; } - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); + mh = MethodHandles.insertArguments(castReference, 0, type); if (cache != null) cache.put(wrap, mh); return mh; From 2b22a2561758109ba3ec0ce1754f56d3d962df03 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Sat, 1 Mar 2014 11:57:57 -0500 Subject: [PATCH 225/265] 8035813: Broken link in java.lang.Iterable Fixed link to ../util/ Reviewed-by: lancea --- jdk/src/share/classes/java/lang/Iterable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/Iterable.java b/jdk/src/share/classes/java/lang/Iterable.java index eed39388a8f..de91500ce50 100644 --- a/jdk/src/share/classes/java/lang/Iterable.java +++ b/jdk/src/share/classes/java/lang/Iterable.java @@ -82,7 +82,7 @@ public interface Iterable { * * @implSpec * The default implementation creates an - * early-binding + * early-binding * spliterator from the iterable's {@code Iterator}. The spliterator * inherits the fail-fast properties of the iterable's iterator. * From 22bc40c0718927cc12e563bf23bc34c89851c6f1 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sun, 2 Mar 2014 15:56:07 +0000 Subject: [PATCH 226/265] 8010194: java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh fails with "Timed out waiting ..." (sol) Reviewed-by: chegar --- .../inheritedChannel/Launcher.java | 27 +++++++++---------- .../inheritedChannel/Util.java | 25 +++-------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java index aad0e586d20..366fb745fb0 100644 --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java @@ -22,8 +22,6 @@ */ /* - * - * * A Launcher to launch a java process with its standard input, output, * and error streams connected to a socket. */ @@ -40,24 +38,23 @@ public class Launcher { private static native void launch0(String cmdarray[], int fd) throws IOException; private static void launch(String className, String options[], String args[], int fd) throws IOException { - String[] javacmd = Util.javaCommand(); - int options_len = (options == null) ? 0 : options.length; - int args_len = (args == null) ? 0 : args.length; - // java [-options] class [args...] - int len = javacmd.length + options_len + 1 + args_len; - + int optsLen = (options == null) ? 0 : options.length; + int argsLen = (args == null) ? 0 : args.length; + int len = 1 + optsLen + 1 + argsLen; String cmdarray[] = new String[len]; int pos = 0; - for (int i=0; i Date: Sun, 2 Mar 2014 19:21:18 +0000 Subject: [PATCH 227/265] 8035868: Check for JNI pending exceptions in windows/native/sun/net/spi/DefaultProxySelector.c Reviewed-by: alanb --- .../native/sun/net/spi/DefaultProxySelector.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c b/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c index 177b1bcf168..e6727a78084 100644 --- a/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c +++ b/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c @@ -179,6 +179,11 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, */ s = strtok(override, "; "); urlhost = (*env)->GetStringUTFChars(env, host, &isCopy); + if (urlhost == NULL) { + if (!(*env)->ExceptionCheck(env)) + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } while (s != NULL) { if (strncmp(s, urlhost, strlen(s)) == 0) { /** @@ -196,8 +201,11 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, } cproto = (*env)->GetStringUTFChars(env, proto, &isCopy); - if (cproto == NULL) - goto noproxy; + if (cproto == NULL) { + if (!(*env)->ExceptionCheck(env)) + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } /* * Set default port value & proxy type from protocol. @@ -255,7 +263,9 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (pport == 0) pport = defport; jhost = (*env)->NewStringUTF(env, phost); + CHECK_NULL_RETURN(jhost, NULL); isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport); + CHECK_NULL_RETURN(isa, NULL); proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa); return proxy; } From 558cb26d1c1b47aaf3213f5cd453c5402cbd1682 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sun, 2 Mar 2014 19:27:43 +0000 Subject: [PATCH 228/265] 8035897: Better memory allocation for file descriptors greater than 1024 on macosx Reviewed-by: michaelm --- jdk/src/aix/native/java/net/aix_close.c | 5 +- .../native/java/net/PlainDatagramSocketImpl.c | 12 ++- .../solaris/native/java/net/PlainSocketImpl.c | 6 +- .../native/java/net/SocketInputStream.c | 6 +- jdk/src/solaris/native/java/net/bsd_close.c | 34 ++++++-- jdk/src/solaris/native/java/net/linux_close.c | 5 +- jdk/src/solaris/native/java/net/net_util_md.h | 2 +- .../solaris/native/java/net/solaris_close.c | 4 +- .../ServerSocket/AnotherSelectFdsLimit.java | 78 +++++++++++++++++++ 9 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 jdk/test/java/net/ServerSocket/AnotherSelectFdsLimit.java diff --git a/jdk/src/aix/native/java/net/aix_close.c b/jdk/src/aix/native/java/net/aix_close.c index d23d5cfebcf..7f8b16affe2 100644 --- a/jdk/src/aix/native/java/net/aix_close.c +++ b/jdk/src/aix/native/java/net/aix_close.c @@ -61,9 +61,10 @@ #include #include #include - #include +#include "jni.h" + /* * Stack allocated by thread when doing blocking operation */ @@ -383,7 +384,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { * Auto restarts with adjusted timeout if interrupted by * signal other than our wakeup signal. */ -int NET_Timeout(int s, long timeout) { +int NET_Timeout(JNIEnv *unused, int s, long timeout) { long prevtime = 0, newtime; struct timeval t; fdEntry_t *fdEntry = getFdEntry(s); diff --git a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c index 4f779dfe20e..2d1faa09d8e 100644 --- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c +++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c @@ -501,7 +501,8 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, return -1; } if (timeout) { - int ret = NET_Timeout(fd, timeout); + int ret = NET_Timeout(env, fd, timeout); + JNU_CHECK_EXCEPTION_RETURN(env, -1); if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Peek timed out"); @@ -594,7 +595,8 @@ Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this, packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); if (timeout) { - int ret = NET_Timeout(fd, timeout); + int ret = NET_Timeout(env, fd, timeout); + JNU_CHECK_EXCEPTION_RETURN(env, -1); if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); @@ -802,9 +804,11 @@ Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this, retry = JNI_FALSE; if (timeout) { - int ret = NET_Timeout(fd, timeout); + int ret = NET_Timeout(env, fd, timeout); if (ret <= 0) { - if (ret == 0) { + if ((*env)->ExceptionCheck(env)) { + // fall-through, to potentially free, then return + } else if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); } else if (ret == -1) { diff --git a/jdk/src/solaris/native/java/net/PlainSocketImpl.c b/jdk/src/solaris/native/java/net/PlainSocketImpl.c index e1c349576cf..0f842a834d8 100644 --- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c +++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c @@ -670,11 +670,11 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this, /* passing a timeout of 0 to poll will return immediately, but in the case of ServerSocket 0 means infinite. */ if (timeout <= 0) { - ret = NET_Timeout(fd, -1); + ret = NET_Timeout(env, fd, -1); } else { - ret = NET_Timeout(fd, timeout); + ret = NET_Timeout(env, fd, timeout); } - + JNU_CHECK_EXCEPTION(env); if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Accept timed out"); diff --git a/jdk/src/solaris/native/java/net/SocketInputStream.c b/jdk/src/solaris/native/java/net/SocketInputStream.c index 76ef8cd3c23..f8412b325c2 100644 --- a/jdk/src/solaris/native/java/net/SocketInputStream.c +++ b/jdk/src/solaris/native/java/net/SocketInputStream.c @@ -100,9 +100,11 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this, } if (timeout) { - nread = NET_Timeout(fd, timeout); + nread = NET_Timeout(env, fd, timeout); if (nread <= 0) { - if (nread == 0) { + if ((*env)->ExceptionCheck(env)) { + // fall-through, to potentially free, then return + } else if (nread == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Read timed out"); } else if (nread == -1) { diff --git a/jdk/src/solaris/native/java/net/bsd_close.c b/jdk/src/solaris/native/java/net/bsd_close.c index 67856b0ba34..ff51a018b99 100644 --- a/jdk/src/solaris/native/java/net/bsd_close.c +++ b/jdk/src/solaris/native/java/net/bsd_close.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -35,9 +36,10 @@ #include #include #include - #include +#include "jni_util.h" + /* * Stack allocated by thread when doing blocking operation */ @@ -331,9 +333,13 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { * Auto restarts with adjusted timeout if interrupted by * signal other than our wakeup signal. */ -int NET_Timeout(int s, long timeout) { +int NET_Timeout(JNIEnv *env, int s, long timeout) { long prevtime = 0, newtime; struct timeval t, *tp = &t; + fd_set fds; + fd_set* fdsp = NULL; + int allocated = 0; + threadEntry_t self; fdEntry_t *fdEntry = getFdEntry(s); /* @@ -363,20 +369,30 @@ int NET_Timeout(int s, long timeout) { t.tv_usec = 0; } + if (s < FD_SETSIZE) { + fdsp = &fds; + FD_ZERO(fdsp); + } else { + int length = (howmany(s+1, NFDBITS)) * sizeof(int); + fdsp = (fd_set *) calloc(1, length); + if (fdsp == NULL) { + JNU_ThrowOutOfMemoryError(env, "NET_Select native heap allocation failed"); + return 0; + } + allocated = 1; + } + FD_SET(s, fdsp); + for(;;) { - fd_set rfds; int rv; - threadEntry_t self; /* * call select on the fd. If interrupted by our wakeup signal * errno will be set to EBADF. */ - FD_ZERO(&rfds); - FD_SET(s, &rfds); startOp(fdEntry, &self); - rv = select(s+1, &rfds, 0, 0, tp); + rv = select(s+1, fdsp, 0, 0, tp); endOp(fdEntry, &self); /* @@ -390,6 +406,8 @@ int NET_Timeout(int s, long timeout) { newtime = now.tv_sec * 1000 + now.tv_usec / 1000; timeout -= newtime - prevtime; if (timeout <= 0) { + if (allocated != 0) + free(fdsp); return 0; } prevtime = newtime; @@ -397,6 +415,8 @@ int NET_Timeout(int s, long timeout) { t.tv_usec = (timeout % 1000) * 1000; } } else { + if (allocated != 0) + free(fdsp); return rv; } diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c index 8472fa792d3..2c08c16831b 100644 --- a/jdk/src/solaris/native/java/net/linux_close.c +++ b/jdk/src/solaris/native/java/net/linux_close.c @@ -34,9 +34,10 @@ #include #include #include - #include +#include "jni.h" + /* * Stack allocated by thread when doing blocking operation */ @@ -313,7 +314,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { * Auto restarts with adjusted timeout if interrupted by * signal other than our wakeup signal. */ -int NET_Timeout(int s, long timeout) { +int NET_Timeout(JNIEnv *unused, int s, long timeout) { long prevtime = 0, newtime; struct timeval t; fdEntry_t *fdEntry = getFdEntry(s); diff --git a/jdk/src/solaris/native/java/net/net_util_md.h b/jdk/src/solaris/native/java/net/net_util_md.h index e7150da6018..d1cc12b9e27 100644 --- a/jdk/src/solaris/native/java/net/net_util_md.h +++ b/jdk/src/solaris/native/java/net/net_util_md.h @@ -34,7 +34,7 @@ #include -int NET_Timeout(int s, long timeout); +int NET_Timeout(JNIEnv *env, int s, long timeout); int NET_Read(int s, void* buf, size_t len); int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen); diff --git a/jdk/src/solaris/native/java/net/solaris_close.c b/jdk/src/solaris/native/java/net/solaris_close.c index 0cf7b5c96fc..d59c45f3b4e 100644 --- a/jdk/src/solaris/native/java/net/solaris_close.c +++ b/jdk/src/solaris/native/java/net/solaris_close.c @@ -28,6 +28,8 @@ #include #include +#include "jni.h" + /* Support for restartable system calls on Solaris. */ #define RESTARTABLE_RETURN_INT(_cmd) do { \ @@ -86,7 +88,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout)); } -int NET_Timeout(int s, long timeout) { +int NET_Timeout(JNIEnv *unused, int s, long timeout) { int result; struct timeval t; long prevtime, newtime; diff --git a/jdk/test/java/net/ServerSocket/AnotherSelectFdsLimit.java b/jdk/test/java/net/ServerSocket/AnotherSelectFdsLimit.java new file mode 100644 index 00000000000..391c5fb0094 --- /dev/null +++ b/jdk/test/java/net/ServerSocket/AnotherSelectFdsLimit.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035897 + * @summary FD_SETSIZE should be set on macosx + * @run main/othervm AnotherSelectFdsLimit 1023 + * @run main/othervm AnotherSelectFdsLimit 1024 + * @run main/othervm AnotherSelectFdsLimit 1025 + * @run main/othervm AnotherSelectFdsLimit 1600 + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.List; + +public class AnotherSelectFdsLimit { + static final int DEFAULT_FDS_TO_USE = 1600; + + public static void main(String [] args) throws Exception { + if (!System.getProperty("os.name").contains("OS X")) { + System.out.println("Test only run on MAC. Exiting."); + return; + } + + int fdsToUse = DEFAULT_FDS_TO_USE; + if (args.length == 1) + fdsToUse = Integer.parseInt(args[0]); + + System.out.println("Using " + fdsToUse + " fds."); + + List threads = new ArrayList<>(); + for (int i=0; i Date: Mon, 3 Mar 2014 10:55:31 +0800 Subject: [PATCH 229/265] 8036104: Rename the PAData.java test Reviewed-by: xuelei --- jdk/test/sun/security/krb5/{PAData.java => TestPAData.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename jdk/test/sun/security/krb5/{PAData.java => TestPAData.java} (99%) diff --git a/jdk/test/sun/security/krb5/PAData.java b/jdk/test/sun/security/krb5/TestPAData.java similarity index 99% rename from jdk/test/sun/security/krb5/PAData.java rename to jdk/test/sun/security/krb5/TestPAData.java index 68fce8f7499..86a4c836739 100644 --- a/jdk/test/sun/security/krb5/PAData.java +++ b/jdk/test/sun/security/krb5/TestPAData.java @@ -30,7 +30,7 @@ import sun.security.krb5.internal.KRBError; import sun.security.krb5.internal.Krb5; import sun.security.util.DerValue; -public class PAData { +public class TestPAData { public static void main(String[] args) throws Exception { // This is the dump of a KRB-ERROR data, no sensitive info included. byte[] bytes = { From 9d91b009c1aef27cc0f5e3ec5072e00bda838268 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 3 Mar 2014 11:06:38 +0000 Subject: [PATCH 230/265] 8035633: TEST_BUG: java/net/NetworkInterface/Equals.java and some tests failed on windows intermittently Reviewed-by: chegar, alanb, igerasim --- jdk/test/java/net/MulticastSocket/TestInterfaces.java | 5 +++-- jdk/test/java/net/NetworkInterface/Equals.java | 5 +++-- jdk/test/java/net/NetworkInterface/IndexTest.java | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/net/MulticastSocket/TestInterfaces.java b/jdk/test/java/net/MulticastSocket/TestInterfaces.java index cb8c6b00f0f..1d87d8d062f 100644 --- a/jdk/test/java/net/MulticastSocket/TestInterfaces.java +++ b/jdk/test/java/net/MulticastSocket/TestInterfaces.java @@ -87,8 +87,9 @@ public class TestInterfaces { continue; } - // JDK-8022963, Skip (Windows) Teredo Tunneling seudo-Interface - if (isWindows && ni.getDisplayName().contains("Teredo")) + // JDK-8022963, Skip (Windows) Teredo Tunneling Pseudo-Interface + String dName = ni.getDisplayName(); + if (isWindows && dName != null && dName.contains("Teredo")) continue; NetworkInterface curr = soc.getNetworkInterface(); diff --git a/jdk/test/java/net/NetworkInterface/Equals.java b/jdk/test/java/net/NetworkInterface/Equals.java index 13dc5fc48e0..8cc81f825a0 100644 --- a/jdk/test/java/net/NetworkInterface/Equals.java +++ b/jdk/test/java/net/NetworkInterface/Equals.java @@ -62,8 +62,9 @@ public class Equals { while (nifs2.hasMoreElements()) { NetworkInterface ni = nifs2.nextElement(); - // JDK-8022963, Skip (Windows)Teredo Tunneling seudo-Interface - if (isWindows && ni.getDisplayName().contains("Teredo")) + // JDK-8022963, Skip (Windows)Teredo Tunneling Pseudo-Interface + String dName = ni.getDisplayName(); + if (isWindows && dName != null && dName.contains("Teredo")) continue; NetworkInterface niOrig = nicMap.get(ni.getName()); diff --git a/jdk/test/java/net/NetworkInterface/IndexTest.java b/jdk/test/java/net/NetworkInterface/IndexTest.java index 58ebb1690f1..a1c65aa920c 100644 --- a/jdk/test/java/net/NetworkInterface/IndexTest.java +++ b/jdk/test/java/net/NetworkInterface/IndexTest.java @@ -40,8 +40,9 @@ public class IndexTest { NetworkInterface nif; while (netifs.hasMoreElements()) { nif = netifs.nextElement(); - // JDK-8022212, Skip (Windows) Teredo Tunneling seudo-Interface - if (nif.getDisplayName().contains("Teredo") && isWindows) + // JDK-8022212, Skip (Windows) Teredo Tunneling Pseudo-Interface + String dName = nif.getDisplayName(); + if (isWindows && dName != null && dName.contains("Teredo")) continue; int index = nif.getIndex(); if (index >= 0) { From bd9b40bbfb53164abbac90ad982636fdc76ae10d Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Mon, 3 Mar 2014 18:17:00 +0400 Subject: [PATCH 231/265] 6946101: ShellScaffold.sh based tests can issue "write error: Broken pipe" messages Reviewed-by: dcubed, sla --- jdk/test/com/sun/jdi/ArrayLengthDumpTest.sh | 4 +- jdk/test/com/sun/jdi/CatchAllTest.sh | 4 +- jdk/test/com/sun/jdi/CatchCaughtTest.sh | 4 +- jdk/test/com/sun/jdi/CatchPatternTest.sh | 5 +- .../com/sun/jdi/CommandCommentDelimiter.sh | 4 +- jdk/test/com/sun/jdi/DeferredStepTest.sh | 3 +- jdk/test/com/sun/jdi/DeoptimizeWalk.sh | 7 +- jdk/test/com/sun/jdi/EvalArgs.sh | 4 +- .../com/sun/jdi/GetLocalVariables3Test.sh | 4 +- .../com/sun/jdi/GetLocalVariables4Test.sh | 4 +- jdk/test/com/sun/jdi/JdbExprTest.sh | 4 +- jdk/test/com/sun/jdi/JdbLockTest.sh | 3 +- jdk/test/com/sun/jdi/JdbMethodExitTest.sh | 7 +- jdk/test/com/sun/jdi/JdbMissStep.sh | 3 +- jdk/test/com/sun/jdi/MixedSuspendTest.sh | 5 +- jdk/test/com/sun/jdi/NotAField.sh | 4 +- jdk/test/com/sun/jdi/NullLocalVariable.sh | 4 +- jdk/test/com/sun/jdi/Redefine-g.sh | 5 +- jdk/test/com/sun/jdi/RedefineAnnotation.sh | 4 +- .../com/sun/jdi/RedefineChangeClassOrder.sh | 4 +- jdk/test/com/sun/jdi/RedefineClasses.sh | 3 +- jdk/test/com/sun/jdi/RedefineException.sh | 5 +- jdk/test/com/sun/jdi/RedefineFinal.sh | 5 +- jdk/test/com/sun/jdi/RedefineImplementor.sh | 4 +- .../com/sun/jdi/RedefineIntConstantToLong.sh | 5 +- jdk/test/com/sun/jdi/RedefineMulti.sh | 5 +- jdk/test/com/sun/jdi/RedefinePop.sh | 5 +- jdk/test/com/sun/jdi/RedefineTTYLineNumber.sh | 4 +- jdk/test/com/sun/jdi/ShellScaffold.sh | 281 +++++++++++------- jdk/test/com/sun/jdi/StringConvertTest.sh | 5 +- jdk/test/com/sun/jdi/WatchFramePop.sh | 4 +- 31 files changed, 234 insertions(+), 178 deletions(-) diff --git a/jdk/test/com/sun/jdi/ArrayLengthDumpTest.sh b/jdk/test/com/sun/jdi/ArrayLengthDumpTest.sh index 9de6aed7412..a1f6b7c5a03 100644 --- a/jdk/test/com/sun/jdi/ArrayLengthDumpTest.sh +++ b/jdk/test/com/sun/jdi/ArrayLengthDumpTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ dojdbCmds() cmd dump this.t[1].length cmd dump ArrayLengthDumpTarg.i.length cmd dump this.length - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/CatchAllTest.sh b/jdk/test/com/sun/jdi/CatchAllTest.sh index aea6325dce2..19b70d99bc8 100644 --- a/jdk/test/com/sun/jdi/CatchAllTest.sh +++ b/jdk/test/com/sun/jdi/CatchAllTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ dojdbCmds() cmd ignore caught java.lang.IndexOutOfBoundsException cmd catch uncaught java.lang.IndexOutOfBoundsException cmd ignore uncaught java.lang.IndexOutOfBoundsException - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/CatchCaughtTest.sh b/jdk/test/com/sun/jdi/CatchCaughtTest.sh index 11fdcb66190..e1665283a55 100644 --- a/jdk/test/com/sun/jdi/CatchCaughtTest.sh +++ b/jdk/test/com/sun/jdi/CatchCaughtTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 cmd catch caught - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/CatchPatternTest.sh b/jdk/test/com/sun/jdi/CatchPatternTest.sh index c2e18fb0500..b467d5c1e52 100644 --- a/jdk/test/com/sun/jdi/CatchPatternTest.sh +++ b/jdk/test/com/sun/jdi/CatchPatternTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,7 @@ dojdbCmds() cmd cont cmd cont cmd ignore all java.lang.I* - cmd cont - cmd quit + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/CommandCommentDelimiter.sh b/jdk/test/com/sun/jdi/CommandCommentDelimiter.sh index f2cfc92c8e8..34f0942824b 100644 --- a/jdk/test/com/sun/jdi/CommandCommentDelimiter.sh +++ b/jdk/test/com/sun/jdi/CommandCommentDelimiter.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ dojdbCmds() cmd 3 \#blah cmd \# connectors cmd step - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/DeferredStepTest.sh b/jdk/test/com/sun/jdi/DeferredStepTest.sh index d7d1f4c7537..528404fefc7 100644 --- a/jdk/test/com/sun/jdi/DeferredStepTest.sh +++ b/jdk/test/com/sun/jdi/DeferredStepTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -129,7 +129,6 @@ dojdbCmds() cmd next; $sleepcmd cmd next; $sleepcmd cmd next; $sleepcmd - cmd quit } mysetup() diff --git a/jdk/test/com/sun/jdi/DeoptimizeWalk.sh b/jdk/test/com/sun/jdi/DeoptimizeWalk.sh index ffc005e8805..c8df10fac0f 100644 --- a/jdk/test/com/sun/jdi/DeoptimizeWalk.sh +++ b/jdk/test/com/sun/jdi/DeoptimizeWalk.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ public class $1 { a4(22); // it passes if this line is commented out System.out.println("jj"); } - + public void a4(int pp) { int v4 = 90; System.out.println("a4: @1 breakpoint here"); @@ -84,8 +84,6 @@ dojdbCmds() #cmd next cmd step cmd where - cmd quit - jdbFailIfNotPresent "shtest\.main" 3 } @@ -108,5 +106,6 @@ mysetup() mysetup runit +jdbFailIfNotPresent "shtest\.main" 3 debuggeeFailIfPresent "Internal exception:" pass diff --git a/jdk/test/com/sun/jdi/EvalArgs.sh b/jdk/test/com/sun/jdi/EvalArgs.sh index 53c1851b58d..aa3e75fdb74 100644 --- a/jdk/test/com/sun/jdi/EvalArgs.sh +++ b/jdk/test/com/sun/jdi/EvalArgs.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -291,8 +291,6 @@ dojdbCmds() cmd eval "$classname.ffjj2($classname.myoranges)" jdbFailIfNotPresent "InvalidTypeException" 3 - - cmd quit } diff --git a/jdk/test/com/sun/jdi/GetLocalVariables3Test.sh b/jdk/test/com/sun/jdi/GetLocalVariables3Test.sh index 6fce8b790ea..2910897d989 100644 --- a/jdk/test/com/sun/jdi/GetLocalVariables3Test.sh +++ b/jdk/test/com/sun/jdi/GetLocalVariables3Test.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 cmd locals - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh b/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh index 45ae52f691e..9af3409b96b 100644 --- a/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh +++ b/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 cmd locals - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/JdbExprTest.sh b/jdk/test/com/sun/jdi/JdbExprTest.sh index 9645714dc08..ecfd9432aed 100644 --- a/jdk/test/com/sun/jdi/JdbExprTest.sh +++ b/jdk/test/com/sun/jdi/JdbExprTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -130,8 +130,6 @@ dojdbCmds() cmd print ~1 jdbFailIfNotPresent "~1 = -2" 3 - - cmd quit } diff --git a/jdk/test/com/sun/jdi/JdbLockTest.sh b/jdk/test/com/sun/jdi/JdbLockTest.sh index b6573a82a73..6558b98a679 100644 --- a/jdk/test/com/sun/jdi/JdbLockTest.sh +++ b/jdk/test/com/sun/jdi/JdbLockTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,6 @@ dojdbCmds() # This should say that main owns the lock # and the sleeper thread is waiting for it. cmd lock $classname.jj - cmd quit } diff --git a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh index ab00816ca6e..86a485ae418 100644 --- a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh +++ b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -232,7 +232,7 @@ dojdbCmds() cmd cont jdbFailIfNotPresent "instance of JdbMethodExitTest" jdbFailIfNotPresent "return value = 8" - + # Get out of bkpt back to the call to traceMethods cmd step up @@ -253,7 +253,7 @@ dojdbCmds() jdbFailIfNotPresent 'Method exited: .* JdbMethodExitTest.traceMethods1' cmd untrace cmd step up - + cmd trace method exits $threadid cmd cont @@ -282,7 +282,6 @@ dojdbCmds() cmd trace go method exit $threadid cmd cont jdbFailIfNotPresent 'Method exited: .*JdbMethodExitTest.traceExit1' - cmd quit } diff --git a/jdk/test/com/sun/jdi/JdbMissStep.sh b/jdk/test/com/sun/jdi/JdbMissStep.sh index a9c5fb5bccc..62c0f3eabf9 100644 --- a/jdk/test/com/sun/jdi/JdbMissStep.sh +++ b/jdk/test/com/sun/jdi/JdbMissStep.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,6 @@ dojdbCmds() cmd stop at $classname'$jj2:20' runToBkpt cmd step - cmd quit } diff --git a/jdk/test/com/sun/jdi/MixedSuspendTest.sh b/jdk/test/com/sun/jdi/MixedSuspendTest.sh index 385b7de6a33..43d0057edfe 100644 --- a/jdk/test/com/sun/jdi/MixedSuspendTest.sh +++ b/jdk/test/com/sun/jdi/MixedSuspendTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -99,8 +99,7 @@ dojdbCmds() { setBkpts @1 runToBkpt @1 - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/NotAField.sh b/jdk/test/com/sun/jdi/NotAField.sh index 20d9916613d..acc627c92ad 100644 --- a/jdk/test/com/sun/jdi/NotAField.sh +++ b/jdk/test/com/sun/jdi/NotAField.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ dojdbCmds() cmd print "java.lang.Class.reflectionFactory.hashCode()" #This should result in a ParseException: ("No such field in ..."): cmd print "java.lang.Class.reflectionFactory.hashCode" - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/NullLocalVariable.sh b/jdk/test/com/sun/jdi/NullLocalVariable.sh index 63bca9545c4..63c0c4aac38 100644 --- a/jdk/test/com/sun/jdi/NullLocalVariable.sh +++ b/jdk/test/com/sun/jdi/NullLocalVariable.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ dojdbCmds() cmd next ; $sleepcmd cmd next ; $sleepcmd cmd locals ; $sleepcmd - cmd cont + cmd allowExit cont } mysetup() diff --git a/jdk/test/com/sun/jdi/Redefine-g.sh b/jdk/test/com/sun/jdi/Redefine-g.sh index 7b518ed3c2a..5641709f412 100644 --- a/jdk/test/com/sun/jdi/Redefine-g.sh +++ b/jdk/test/com/sun/jdi/Redefine-g.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -88,8 +88,7 @@ dojdbCmds() cmd where cmd locals - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineAnnotation.sh b/jdk/test/com/sun/jdi/RedefineAnnotation.sh index 77a69845e74..066e3d3eb4b 100644 --- a/jdk/test/com/sun/jdi/RedefineAnnotation.sh +++ b/jdk/test/com/sun/jdi/RedefineAnnotation.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -217,7 +217,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 redefineClass @1 - cmd cont + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineChangeClassOrder.sh b/jdk/test/com/sun/jdi/RedefineChangeClassOrder.sh index 8d4b6287b8d..b14a42201b3 100644 --- a/jdk/test/com/sun/jdi/RedefineChangeClassOrder.sh +++ b/jdk/test/com/sun/jdi/RedefineChangeClassOrder.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -123,7 +123,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 redefineClass @1 - cmd cont + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineClasses.sh b/jdk/test/com/sun/jdi/RedefineClasses.sh index e1d013a783e..f323712d305 100644 --- a/jdk/test/com/sun/jdi/RedefineClasses.sh +++ b/jdk/test/com/sun/jdi/RedefineClasses.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,6 @@ dojdbCmds() cmd redefine $classname $tmpFileDir/$classname.class cmd redefine $classname $tmpFileDir/$classname.class cmd redefine $classname $tmpFileDir/$classname.class - cmd quit } diff --git a/jdk/test/com/sun/jdi/RedefineException.sh b/jdk/test/com/sun/jdi/RedefineException.sh index f66d2c5e456..e1bc0a3b215 100644 --- a/jdk/test/com/sun/jdi/RedefineException.sh +++ b/jdk/test/com/sun/jdi/RedefineException.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -92,8 +92,7 @@ dojdbCmds() runToBkpt redefineClass @1 cmd pop - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineFinal.sh b/jdk/test/com/sun/jdi/RedefineFinal.sh index 80ec5254e4a..16381381b14 100644 --- a/jdk/test/com/sun/jdi/RedefineFinal.sh +++ b/jdk/test/com/sun/jdi/RedefineFinal.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,7 @@ dojdbCmds() setBkpts @1 contToBkpt cmd where - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineImplementor.sh b/jdk/test/com/sun/jdi/RedefineImplementor.sh index 4deb347f4b4..dd7f83e8a0c 100644 --- a/jdk/test/com/sun/jdi/RedefineImplementor.sh +++ b/jdk/test/com/sun/jdi/RedefineImplementor.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ dojdbCmds() setBkpts @1 runToBkpt @1 redefineClass @1 - cmd cont + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh b/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh index ab921c0cd48..4f384dff504 100644 --- a/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh +++ b/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2014 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,7 @@ dojdbCmds() setBkpts @1 contToBkpt cmd where - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineMulti.sh b/jdk/test/com/sun/jdi/RedefineMulti.sh index a51c3b16398..e2736cb0b5f 100644 --- a/jdk/test/com/sun/jdi/RedefineMulti.sh +++ b/jdk/test/com/sun/jdi/RedefineMulti.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -126,8 +126,7 @@ dojdbCmds() setBkpts @1 contToBkpt redefineClass @2 - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefinePop.sh b/jdk/test/com/sun/jdi/RedefinePop.sh index 4059a1a9e5d..c92e83d2f70 100644 --- a/jdk/test/com/sun/jdi/RedefinePop.sh +++ b/jdk/test/com/sun/jdi/RedefinePop.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,7 @@ dojdbCmds() runToBkpt @1 redefineClass @1 cmd pop - cmd cont - cmd quit + cmd allowExit cont } diff --git a/jdk/test/com/sun/jdi/RedefineTTYLineNumber.sh b/jdk/test/com/sun/jdi/RedefineTTYLineNumber.sh index addf45ca2b2..8bc7a845ef2 100644 --- a/jdk/test/com/sun/jdi/RedefineTTYLineNumber.sh +++ b/jdk/test/com/sun/jdi/RedefineTTYLineNumber.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,6 @@ dojdbCmds() cmd stop in shtest.A contToBkpt #jdbFailIfNotPresent "System\.out\.println" 3 - cmd quit - } diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index 7bc063d44eb..eb3b65bf30b 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -190,11 +190,15 @@ killOrphans() echo "$1: kill -9 $toBeKilled" >& 2 kill -9 $toBeKilled fi -} +} +# Returns 0 if $1 is the pid of a running process findPid() { - # Return 0 if $1 is the pid of a running process. + if [ -z "$1" ] ; then + return 1 + fi + if [ -z "$isWin98" ] ; then if [ "$osname" = SunOS ] ; then # Solaris and OpenSolaris use pgrep and not ps in psCmd @@ -208,7 +212,7 @@ findPid() # cygwin ps puts an I in column 1 for some reason. findPidCmd="$psCmd -e" fi - $findPidCmd | $grep '^I* *'"$1 " > $devnull 2>&1 + $findPidCmd | $grep '^I* *'"$1 " > $devnull 2>&1 return $? fi @@ -245,56 +249,55 @@ setup() echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test." exit 1 fi - + ulimitCmd= osname=`uname -s` isWin98= isCygwin= case "$osname" in - Windows* | CYGWIN*) - devnull=NUL - if [ "$osname" = Windows_98 -o "$osname" = Windows_ME ]; then - isWin98=1 - debuggeeKeyword='we_cant_kill_debuggees_on_win98' - jdbKeyword='jdb\.exe' - fi + Windows* | CYGWIN*) + devnull=NUL + if [ "$osname" = Windows_98 -o "$osname" = Windows_ME ]; then + isWin98=1 + debuggeeKeyword='we_cant_kill_debuggees_on_win98' + jdbKeyword='jdb\.exe' + fi + case "$osname" in + CYGWIN*) + isCygwin=1 + devnull=/dev/null + ;; + esac - case "$osname" in - CYGWIN*) - isCygwin=1 - devnull=/dev/null - ;; - esac - - if [ -r $jdk/bin/dt_shmem.dll -o -r $jdk/jre/bin/dt_shmem.dll ] ; then - transport=dt_shmem - address=kkkk.$$ - else - transport=dt_socket - address= - fi - baseArgs="$baseArgs -XX:-ShowMessageBoxOnError" - # jtreg puts \\s in TESTCLASSES and some uses, eg. echo - # treat them as control chars on mks (eg \t is tab) - # Oops; windows mks really seems to want this cat line - # to start in column 1 - if [ -w "$SystemRoot" ] ; then - tmpFile=$SystemRoot/tmp.$$ - elif [ -w "$SYSTEMROOT" ] ; then - tmpFile=$SYSTEMROOT/tmp.$$ - else - tmpFile=tmp.$$ - fi + if [ -r $jdk/bin/dt_shmem.dll -o -r $jdk/jre/bin/dt_shmem.dll ] ; then + transport=dt_shmem + address=kkkk.$$ + else + transport=dt_socket + address= + fi + baseArgs="$baseArgs -XX:-ShowMessageBoxOnError" + # jtreg puts \\s in TESTCLASSES and some uses, eg. echo + # treat them as control chars on mks (eg \t is tab) + # Oops; windows mks really seems to want this cat line + # to start in column 1 + if [ -w "$SystemRoot" ] ; then + tmpFile=$SystemRoot/tmp.$$ + elif [ -w "$SYSTEMROOT" ] ; then + tmpFile=$SYSTEMROOT/tmp.$$ + else + tmpFile=tmp.$$ + fi cat <$tmpFile $TESTCLASSES EOF - TESTCLASSES=`cat $tmpFile | sed -e 's@\\\\@/@g'` - rm -f $tmpFile - # on mks - grep=egrep - psCmd=ps - jstack=jstack.exe - ;; + TESTCLASSES=`cat $tmpFile | sed -e 's@\\\\@/@g'` + rm -f $tmpFile + # on mks + grep=egrep + psCmd=ps + jstack=jstack.exe + ;; SunOS | Linux | Darwin | AIX) transport=dt_socket address= @@ -378,7 +381,7 @@ EOF # linux same as above # win mks: No dice; processes still running trap "cleanup" 0 1 2 3 4 6 9 10 15 - + jdbOptions="$jdbOptions -J-D${jdbKeyword}" } @@ -397,7 +400,7 @@ docompile() cp $classname.java.1 $classname.java echo "--Compiling first version of `pwd`/$classname.java with options: $compileOptions" # Result is in $pkgSlash$classname.class - + if [ -z "$javacCmd" ] ; then javacCmd=$jdk/bin/javac fi @@ -523,29 +526,52 @@ docompile() # If it ever becomes necessary to send a jdb command before # a main[10] form of prompt appears, then this # code will have to be modified. -cmd() +# +# Specify $1 = allowExit to show that the command given +# allows JDB to exit +cmd() { - if [ $1 = quit -o -r "$failFile" ] ; then - # if jdb got a cont cmd that caused the debuggee - # to run to completion, jdb can be gone before - # we get here. - echo "--Sending cmd: quit" >& 2 - echo quit - # See 6562090. Maybe there is a way that the exit - # can cause jdb to not get the quit. - sleep 5 + allowExit= + case "$1" in + allowExit) + allowExit="allowExit" + shift + ;; + exitJdb) + # Quit JDB only with this cmd() invocation + echo "--Sending cmd: quit" >& 2 + echo quit + echo "--Quit cmd was sent" >& 2 + # See 6562090. Maybe there is a way that the exit + # can cause jdb to not get the quit. + sleep 5 - # The exit code value here doesn't matter since this function - # is called as part of a pipeline and it is not the last command - # in the pipeline. - exit 1 + # The exit code value here doesn't matter since this function + # is called as part of a pipeline and it is not the last command + # in the pipeline. + exit 1 + ;; + esac + command=$* + + if [ -z "$command" ] ; then + dofail "Command can't be a null string. Test failure" fi - + if [ "$command" = "quit" -o "$command" = "exit" ] ; then + # We don't want the test to manually quit jdb, + # we will do it in the end automatically + dofail "It's not allowed to send quit or exit commands from the test" + fi + if [ -r "$failFile" ] ; then + # failFile exists, it's better to finish execution + dofinish "quit" + fi + # $jdbOutFile always exists here and is non empty # because after starting jdb, we waited # for the prompt. fileSize=`wc -c $jdbOutFile | awk '{ print $1 }'` - echo "--Sending cmd: " $* >&2 + echo "--Sending cmd: " $command >&2 # jjh: We have a few intermittent failures here. # It is as if every so often, jdb doesn't @@ -570,7 +596,7 @@ cmd() # And, we know jdb is started because the main[1] output is in the .jtr # file. And, we wouldn't have gotten here if mydojdbcmds hadn't # seen the ]. - echo $* + echo $command # Now we have to wait for the next jdb prompt. We wait for a pattern # to appear in the last line of jdb output. Normally, the prompt is @@ -644,7 +670,7 @@ cmd() # wait for 4 new chars to appear in the jdb output count=0 desiredFileSize=`expr $fileSize + 4` - msg1=`echo At start: cmd/size/waiting : $* / $fileSize / \`date\`` + msg1=`echo At start: cmd/size/waiting : $command / $fileSize / \`date\`` while [ 1 = 1 ] ; do newFileSize=`wc -c $jdbOutFile | awk '{ print $1 } '` #echo jj: desired = $desiredFileSize, new = $newFileSize >& 2 @@ -657,7 +683,7 @@ cmd() count=`expr $count + 1` if [ $count = 30 -o $count = 60 ] ; then # record some debug info. - echo "--DEBUG: jdb $$ didn't responded to command in $count secs: $*" >& 2 + echo "--DEBUG: jdb $$ didn't responded to command in $count secs: $command" >& 2 echo "--DEBUG:" $msg1 >& 2 echo "--DEBUG: "done size/waiting : / $newFileSize / `date` >& 2 echo "-- $jdbOutFile follows-------------------------------" >& 2 @@ -666,13 +692,12 @@ cmd() dojstack #$psCmd | sed -e '/com.sun.javatest/d' -e '/nsk/d' >& 2 if [ $count = 60 ] ; then - dofail "jdb never responded to command: $*" + dofail "jdb never responded to command: $command" fi fi done # Note that this assumes just these chars in thread names. - waitForJdbMsg '[a-zA-Z0-9_-][a-zA-Z0-9_-]*\[[1-9][0-9]*\] [ >]*$' \ - 1 allowExit + waitForJdbMsg '[a-zA-Z0-9_-][a-zA-Z0-9_-]*\[[1-9][0-9]*\] [ >]*$' 1 $allowExit } setBkpts() @@ -681,12 +706,13 @@ setBkpts() # $1 is the bkpt name, eg, @1 allLines=`$grep -n "$1 *breakpoint" $tmpFileDir/$classname.java.1 | sed -e 's@^\([0-9]*\).*@\1@g'` for ii in $allLines ; do - cmd stop at $pkgDot$classname:$ii + cmd "stop at $pkgDot$classname:$ii" done } runToBkpt() { + # Don't pass allowExit here as we don't want JDB to unexpectedly exit cmd run # Don't need to do this - the above waits for the next prompt which comes out # AFTER the Breakpoint hit message. @@ -696,6 +722,7 @@ runToBkpt() contToBkpt() { + # Don't pass allowExit here as we don't want JDB to unexpectedly exit cmd cont # Don't need to do this - the above waits for the next prompt which comes out # AFTER the Breakpoint hit message. @@ -723,22 +750,24 @@ waitForJdbMsg() # Found desired string break fi - fi - tail -2 $jdbOutFile | $grep -s "The application exited" > $devnull 2>&1 - if [ $? = 0 ] ; then + fi + tail -2 $jdbOutFile | $grep -s "The application exited" > $devnull 2>&1 + if [ $? = 0 ] ; then # Found 'The application exited' + echo "--JDB finished: The application exited" >&2 if [ ! -z "$allowExit" ] ; then - break + # Exit is allowed + dofinish fi # Otherwise, it is an error if we don't find $1 - if [ -r $jdbOutFile ] ; then - tail -$nlines $jdbOutFile | $grep -s "$1" > $devnull 2>&1 + if [ -r $jdbOutFile ] ; then + tail -$nlines $jdbOutFile | $grep -s "$1" > $devnull 2>&1 if [ $? = 0 ] ; then - break - fi - fi - dofail "Waited for jdb msg $1, but it never appeared" - fi + break + fi + fi + dofail "JDB unexpectedly finished: Waited for jdb msg $1, but it never appeared" + fi sleep ${sleep_seconds} findPid $topPid @@ -761,6 +790,19 @@ waitForJdbMsg() } +# Finishes JDB execution +# Specify command to finish if it's needed +dofinish() +{ + if [ ! -z "$*" ] ; then + echo "--Finish execution with sending \"$*\" command to JDB" >&2 + cmd "exitJdb" "$*" + else + echo "--Finish without sending \"quit\" command to JDB" >&2 + fi + exit 0 +} + # $1 is the string to print. If $2 exists, # it is the name of a file to print, ie, the name # of the file that contains the $1 string. @@ -774,10 +816,11 @@ dofail() # Kill the debuggee ; it could be hung so # we want to get rid of it as soon as possible. killOrphans "killing debuggee" $debuggeeKeyword + # Kill debugger, it could be hung + killOrphans "killing debugger" $jdbKeyword echo " " >>$failFile echo "--Fail: $*" >> $failFile - echo quit fi if [ ! -z "$2" ] ; then echo "---- contents of $2 follows -------" >> $failFile @@ -788,7 +831,7 @@ dofail() } -redefineClass() +redefineClass() { if [ -z "$1" ] ; then vers=2 @@ -796,8 +839,8 @@ redefineClass() vers=`echo $1 | sed -e 's/@//'` vers=`expr $vers + 1` fi - - cmd redefine $pkgDot$classname $tmpFileDir/vers$vers/$classname.class + + cmd "redefine $pkgDot$classname $tmpFileDir/vers$vers/$classname.class" cp $tmpFileDir/$classname.java.$vers \ $tmpFileDir/$classname.java @@ -807,8 +850,10 @@ mydojdbCmds() { # Wait for jdb to start before we start sending cmds waitForJdbMsg ']' 1 + # Send commands from the test dojdbCmds - cmd quit + # Finish jdb with quit command + dofinish "quit" } startJdb() @@ -853,7 +898,7 @@ startDebuggee() if [ -r $TESTCLASSES/../@debuggeeVMOptions ] ; then args=`cat $TESTCLASSES/../@debuggeeVMOptions` fi - + if [ ! -z "$args" ] ; then echo "--Starting debuggee with args from @debuggeeVMOptions: $args" else @@ -932,16 +977,13 @@ waitForFinish() break fi if [ ! -z "$isWin98" ] ; then - $psCmd | $grep -i 'JDB\.EXE' >$devnull 2>&1 - if [ $? != 0 ] ; then - break; - fi - fi - $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 - if [ $? = 0 ] ; then - #something went wrong - dofail "jdb input stream closed prematurely" + $psCmd | $grep -i 'JDB\.EXE' >$devnull 2>&1 + if [ $? != 0 ] ; then + break + fi fi + # Something went wrong + jdbFailIfPresent "Input stream closed" # If a failure has occured, quit if [ -r "$failFile" ] ; then @@ -951,6 +993,46 @@ waitForFinish() sleep ${sleep_seconds} done + # jdb exited because its input stream closed prematurely + jdbFailIfPresent "Input stream closed" + + # It is necessary here to avoid the situation when JDB exited but + # mydojdbCmds() didn't finish because it waits for JDB message + # in waitForJdbMsg(), at the same time main process will finish + # the execution with no errors. + # To avoid that, wait for spawned processes to finish + case "$osname" in + SunOS) + # `wait` function doesn't work in Solaris shell as in bash, + # so create replacement that finds mydojdbCmds() shell process + # and waits for its finish + cmdsPid= + # get list of processes except main process with $topPid + processes=`$psCmd | $grep -v "$grep" | $grep -v $topPid | awk '{print $1}'` + for pid in $processes; do + # for each process grep its full args string for test name $0 + # $0 contains full test name with path + pargs -l $pid 2>$devnull | $grep "$0" >$devnull 2>&1 + if [ $? = 0 ] ; then + cmdsPid=$pid + break + fi + done + echo "--waitForFinish: Waiting for mydojdbCmds() to finish" >&2 + while [ 1 = 1 ] ; do + findPid $cmdsPid + if [ $? != 0 ] ; then + break + fi + sleep ${sleep_seconds} + done + ;; + *) + echo "--waitForFinish: Waiting for all processes to finish" >&2 + wait + ;; + esac + if [ -r "$failFile" ] ; then ls -l "$failFile" >&2 echo "" >&2 @@ -1130,13 +1212,8 @@ pass() runit() { setup - runitAfterSetup -} - -runitAfterSetup() -{ docompile - startJdb + startJdb startDebuggee waitForFinish diff --git a/jdk/test/com/sun/jdi/StringConvertTest.sh b/jdk/test/com/sun/jdi/StringConvertTest.sh index c86ab3dab46..181105c6257 100644 --- a/jdk/test/com/sun/jdi/StringConvertTest.sh +++ b/jdk/test/com/sun/jdi/StringConvertTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -164,7 +164,7 @@ dojdbCmds() cmd print "$classname.growit(\"xyz\")" cmd eval "$classname.sbGrower.append(\"xyz\")" cmd print 1 - + cmd eval "sbTim.toString()" cmd print 1 @@ -183,7 +183,6 @@ dojdbCmds() cmd print "this.ivar" cmd print gusLoc cmd print 1 - cmd quit } mysetup() diff --git a/jdk/test/com/sun/jdi/WatchFramePop.sh b/jdk/test/com/sun/jdi/WatchFramePop.sh index 5aa7905cac7..870f32f0a3c 100644 --- a/jdk/test/com/sun/jdi/WatchFramePop.sh +++ b/jdk/test/com/sun/jdi/WatchFramePop.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ dojdbCmds() contToBkpt # stops at the bkpt at cmd next # The bug is that this next runs to completion # In which case, so does jdb - cmd quit # so we never get here. + # so we never get here. } From c96fd46a4c6dfa25b01b971ff8e06d146f9303de Mon Sep 17 00:00:00 2001 From: Mattias Tobiasson Date: Fri, 28 Feb 2014 13:38:51 +0100 Subject: [PATCH 232/265] 6625574: java/lang/management/MemoryMXBean/Pending.java fails: "pending finalization = 0 but expected > 0" Move local objs variable to a static public so the the optimizer will not remove it unexpectedly. Reviewed-by: sla --- jdk/test/java/lang/management/MemoryMXBean/Pending.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/management/MemoryMXBean/Pending.java b/jdk/test/java/lang/management/MemoryMXBean/Pending.java index cc0235f58f7..678bc7e4ca7 100644 --- a/jdk/test/java/lang/management/MemoryMXBean/Pending.java +++ b/jdk/test/java/lang/management/MemoryMXBean/Pending.java @@ -76,6 +76,9 @@ public class Pending { System.out.println("Test passed."); } + // Keep objs public so the optimizer will not remove them too early. + public static Object[] objs = null; + private static void test() throws Exception { // Clean the memory and remove all objects that are pending // finalization @@ -105,7 +108,7 @@ public class Pending { System.out.println(" Afer creating objects with no ref: " + snapshot); printFinalizerInstanceCount(); - Object[] objs = new Object[REF_COUNT]; + objs = new Object[REF_COUNT]; for (int i = 0; i < REF_COUNT; i++) { objs[i] = new MyObject(); } From 227129c4d96eaf253841741c2c18be6dec82f470 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 28 Feb 2014 13:44:16 +0100 Subject: [PATCH 233/265] 8031754: Type speculation should favor profile data from outermost inlined method Favor profile data coming from outer most method Reviewed-by: kvn, twisti --- hotspot/src/share/vm/opto/c2_globals.hpp | 4 + hotspot/src/share/vm/opto/graphKit.cpp | 29 +-- hotspot/src/share/vm/opto/type.cpp | 213 +++++++++++++++++------ hotspot/src/share/vm/opto/type.hpp | 47 +++-- 4 files changed, 216 insertions(+), 77 deletions(-) diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index a22d6871ad6..cc5e2ced6b3 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -653,6 +653,10 @@ experimental(bool, UseTypeSpeculation, false, \ "Speculatively propagate types from profiles") \ \ + diagnostic(bool, UseInlineDepthForSpeculativeTypes, true, \ + "Carry inline depth of profile point with speculative type " \ + "and give priority to profiling from lower inline depth") \ + \ product_pd(bool, TrapBasedRangeChecks, \ "Generate code for range checks that uses a cmp and trap " \ "instruction raising SIGTRAP. Used on PPC64.") \ diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index d2876a93a5e..17422fa4f8c 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -2113,30 +2113,33 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) { * @return node with improved type */ Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { - const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr(); + const Type* current_type = _gvn.type(n); assert(UseTypeSpeculation, "type speculation must be on"); - if (exact_kls != NULL && - // nothing to improve if type is already exact - (current_type == NULL || - (!current_type->klass_is_exact() && - (current_type->speculative() == NULL || - !current_type->speculative()->klass_is_exact())))) { + + const TypeOopPtr* speculative = current_type->speculative(); + + if (current_type->would_improve_type(exact_kls, jvms()->depth())) { const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); const TypeOopPtr* xtype = tklass->as_instance_type(); assert(xtype->klass_is_exact(), "Should be exact"); + // record the new speculative type's depth + speculative = xtype->with_inline_depth(jvms()->depth()); + } + if (speculative != current_type->speculative()) { // Build a type with a speculative type (what we think we know // about the type but will need a guard when we use it) - const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype); - // We're changing the type, we need a new cast node to carry the - // new type. The new type depends on the control: what profiling - // tells us is only valid from here as far as we can tell. - Node* cast = new(C) CastPPNode(n, spec_type); - cast->init_req(0, control()); + const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, speculative); + // We're changing the type, we need a new CheckCast node to carry + // the new type. The new type depends on the control: what + // profiling tells us is only valid from here as far as we can + // tell. + Node* cast = new(C) CheckCastPPNode(control(), n, current_type->remove_speculative()->join_speculative(spec_type)); cast = _gvn.transform(cast); replace_in_map(n, cast); n = cast; } + return n; } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index b957a227eb6..d2591735770 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2463,7 +2463,7 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const { const TypeOopPtr *TypeOopPtr::BOTTOM; //------------------------------TypeOopPtr------------------------------------- -TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative) +TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) : TypePtr(t, ptr, offset), _const_oop(o), _klass(k), _klass_is_exact(xk), @@ -2471,7 +2471,8 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int o _is_ptr_to_narrowklass(false), _is_ptr_to_boxed_value(false), _instance_id(instance_id), - _speculative(speculative) { + _speculative(speculative), + _inline_depth(inline_depth){ if (Compile::current()->eliminate_boxing() && (t == InstPtr) && (offset > 0) && xk && (k != 0) && k->is_instance_klass()) { _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset); @@ -2538,12 +2539,12 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int o //------------------------------make------------------------------------------- const TypeOopPtr *TypeOopPtr::make(PTR ptr, - int offset, int instance_id, const TypeOopPtr* speculative) { + int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { assert(ptr != Constant, "no constant generic pointers"); ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; ciObject* o = NULL; - return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative))->hashcons(); + return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative, inline_depth))->hashcons(); } @@ -2551,7 +2552,7 @@ const TypeOopPtr *TypeOopPtr::make(PTR ptr, const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); if( ptr == _ptr ) return this; - return make(ptr, _offset, _instance_id, _speculative); + return make(ptr, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- @@ -2648,7 +2649,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; - return make(ptr, offset, instance_id, speculative); + return make(ptr, offset, instance_id, speculative, _inline_depth); } case BotPTR: case NotNull: @@ -2661,7 +2662,8 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { const TypeOopPtr *tp = t->is_oopptr(); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative); + int depth = meet_inline_depth(tp->inline_depth()); + return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth); } case InstPtr: // For these, flip the call around to cut down @@ -2678,7 +2680,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { const Type *TypeOopPtr::xdual() const { assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); assert(const_oop() == NULL, "no constants here"); - return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); + return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); } //--------------------------make_from_klass_common----------------------------- @@ -2769,7 +2771,7 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, } else if (!o->should_be_constant()) { return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } - const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, is_autobox_cache); + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, InlineDepthBottom, is_autobox_cache); return arr; } else if (klass->is_type_array_klass()) { // Element is an typeArray @@ -2858,7 +2860,8 @@ bool TypeOopPtr::eq( const Type *t ) const { const TypeOopPtr *a = (const TypeOopPtr*)t; if (_klass_is_exact != a->_klass_is_exact || _instance_id != a->_instance_id || - !eq_speculative(a)) return false; + !eq_speculative(a) || + _inline_depth != a->_inline_depth) return false; ciObject* one = const_oop(); ciObject* two = a->const_oop(); if (one == NULL || two == NULL) { @@ -2876,6 +2879,7 @@ int TypeOopPtr::hash(void) const { _klass_is_exact + _instance_id + hash_speculative() + + _inline_depth + TypePtr::hash(); } @@ -2896,6 +2900,7 @@ void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } @@ -2909,6 +2914,16 @@ void TypeOopPtr::dump_speculative(outputStream *st) const { st->print(")"); } } + +void TypeOopPtr::dump_inline_depth(outputStream *st) const { + if (_inline_depth != InlineDepthBottom) { + if (_inline_depth == InlineDepthTop) { + st->print(" (inline_depth=InlineDepthTop)"); + } else { + st->print(" (inline_depth=%d)", _inline_depth); + } + } +} #endif //------------------------------singleton-------------------------------------- @@ -2922,7 +2937,7 @@ bool TypeOopPtr::singleton(void) const { //------------------------------add_offset------------------------------------- const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { - return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); + return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); } /** @@ -2932,7 +2947,52 @@ const Type* TypeOopPtr::remove_speculative() const { if (_speculative == NULL) { return this; } - return make(_ptr, _offset, _instance_id, NULL); + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, _offset, _instance_id, NULL, _inline_depth); +} + +/** + * Return same type but with a different inline depth (used for speculation) + * + * @param depth depth to meet with + */ +const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, _offset, _instance_id, _speculative, depth); +} + +/** + * Check whether new profiling would improve speculative type + * + * @param exact_kls class from profiling + * @param inline_depth inlining depth of profile point + * + * @return true if type profile is valuable + */ +bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { + // no way to improve an already exact type + if (klass_is_exact()) { + return false; + } + // no profiling? + if (exact_kls == NULL) { + return false; + } + // no speculative type or non exact speculative type? + if (speculative_type() == NULL) { + return true; + } + // If the node already has an exact speculative type keep it, + // unless it was provided by profiling that is at a deeper + // inlining level. Profiling at a higher inlining depth is + // expected to be less accurate. + if (_speculative->inline_depth() == InlineDepthBottom) { + return false; + } + assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison"); + return inline_depth < _speculative->inline_depth(); } //------------------------------meet_instance_id-------------------------------- @@ -3035,6 +3095,21 @@ int TypeOopPtr::hash_speculative() const { return _speculative->hash(); } +/** + * dual of the inline depth for this type (used for speculation) + */ +int TypeOopPtr::dual_inline_depth() const { + return -inline_depth(); +} + +/** + * meet of 2 inline depth (used for speculation) + * + * @param depth depth to meet with + */ +int TypeOopPtr::meet_inline_depth(int depth) const { + return MAX2(inline_depth(), depth); +} //============================================================================= // Convenience common pre-built types. @@ -3045,8 +3120,8 @@ const TypeInstPtr *TypeInstPtr::MARK; const TypeInstPtr *TypeInstPtr::KLASS; //------------------------------TypeInstPtr------------------------------------- -TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative) - : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative), _name(k->name()) { +TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth) + : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) { assert(k != NULL && (k->is_loaded() || o == NULL), "cannot have constants with non-loaded klass"); @@ -3059,7 +3134,8 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, ciObject* o, int offset, int instance_id, - const TypeOopPtr* speculative) { + const TypeOopPtr* speculative, + int inline_depth) { assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant assert( (!o && ptr != Constant) || (o && ptr == Constant), @@ -3080,7 +3156,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, // Now hash this baby TypeInstPtr *result = - (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative))->hashcons(); + (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative, inline_depth))->hashcons(); return result; } @@ -3113,7 +3189,7 @@ const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; // Reconstruct _sig info here since not a problem with later lazy // construction, _sig will show up on demand. - return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative); + return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3125,13 +3201,13 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const { ciInstanceKlass* ik = _klass->as_instance_klass(); if( (ik->is_final() || _const_oop) ) return this; // cannot clear xk if( ik->is_interface() ) return this; // cannot set xk - return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative); + return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative); + return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth); } //------------------------------xmeet_unloaded--------------------------------- @@ -3142,6 +3218,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tinst); + int depth = meet_inline_depth(tinst->inline_depth()); const TypeInstPtr *loaded = is_loaded() ? this : tinst; const TypeInstPtr *unloaded = is_loaded() ? tinst : this; @@ -3162,7 +3239,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { assert(loaded->ptr() != TypePtr::Null, "insanity check"); // if( loaded->ptr() == TypePtr::TopPTR ) { return unloaded; } - else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative); } + else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative, depth); } else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) { if (unloaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } @@ -3219,6 +3296,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3226,12 +3304,12 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // below the centerline when the superclass is exact. We need to // do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { - return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); + return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); + return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); } case Constant: case NotNull: @@ -3246,7 +3324,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { // that is, tp's array type is a subtype of my klass return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), - tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); + tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } } // The other case cannot happen, since I cannot be a subtype of an array. @@ -3254,7 +3332,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; - return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); + return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); default: typerr(t); } } @@ -3269,14 +3347,16 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); return make(ptr, klass(), klass_is_exact(), - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth); } case NotNull: case BotPTR: { int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return TypeOopPtr::make(ptr, offset, instance_id, speculative); + int depth = meet_inline_depth(tp->inline_depth()); + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } default: typerr(t); } @@ -3296,7 +3376,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; return make(ptr, klass(), klass_is_exact(), - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, _inline_depth); } case NotNull: case BotPTR: @@ -3328,13 +3408,14 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tinst); + int depth = meet_inline_depth(tinst->inline_depth()); // Check for easy case; klasses are equal (and perhaps not loaded!) // If we have constants, then we created oops so classes are loaded // and we can handle the constants further down. This case handles // both-not-loaded or both-loaded classes if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) { - return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative); + return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative, depth); } // Classes require inspection in the Java klass hierarchy. Must be loaded. @@ -3398,7 +3479,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // Find out which constant. o = (this_klass == klass()) ? const_oop() : tinst->const_oop(); } - return make(ptr, k, xk, o, off, instance_id, speculative); + return make(ptr, k, xk, o, off, instance_id, speculative, depth); } // Either oop vs oop or interface vs interface or interface vs Object @@ -3475,7 +3556,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { else ptr = NotNull; } - return make(ptr, this_klass, this_xk, o, off, instance_id, speculative); + return make(ptr, this_klass, this_xk, o, off, instance_id, speculative, depth); } // Else classes are not equal // Since klasses are different, we require a LCA in the Java @@ -3486,7 +3567,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tinst_klass); - return make(ptr, k, false, NULL, off, instance_id, speculative); + return make(ptr, k, false, NULL, off, instance_id, speculative, depth); } // End of case InstPtr } // End of switch @@ -3510,7 +3591,7 @@ ciType* TypeInstPtr::java_mirror_type() const { // Dual: do NOT dual on klasses. This means I do NOT understand the Java // inheritance mechanism. const Type *TypeInstPtr::xdual() const { - return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); + return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); } //------------------------------eq--------------------------------------------- @@ -3567,6 +3648,7 @@ void TypeInstPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } #endif @@ -3580,7 +3662,15 @@ const Type *TypeInstPtr::remove_speculative() const { if (_speculative == NULL) { return this; } - return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL); + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL, _inline_depth); +} + +const TypeOopPtr *TypeInstPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, depth); } //============================================================================= @@ -3597,30 +3687,30 @@ const TypeAryPtr *TypeAryPtr::FLOATS; const TypeAryPtr *TypeAryPtr::DOUBLES; //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); if (!xk) xk = ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative, inline_depth))->hashcons(); } //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, bool is_autobox_cache) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth, bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; - return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); + return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3629,13 +3719,13 @@ const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; if (!UseExactTypes) return this; if (_ary->ary_must_be_exact()) return this; // cannot clear xk - return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative); + return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative); + return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); } //-----------------------------narrow_size_type------------------------------- @@ -3698,7 +3788,7 @@ const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { new_size = narrow_size_type(new_size); if (new_size == size()) return this; const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable()); - return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3777,19 +3867,20 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { const TypeOopPtr *tp = t->is_oopptr(); int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); + int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = xmeet_speculative(tp); return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return TypeOopPtr::make(ptr, offset, instance_id, speculative); + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); } @@ -3813,7 +3904,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, _inline_depth); } default: ShouldNotReachHere(); } @@ -3830,6 +3921,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tap); + int depth = meet_inline_depth(tap->inline_depth()); ciKlass* lazy_klass = NULL; if (tary->_elem->isa_int()) { // Integral array element types have irrelevant lattice relations. @@ -3870,7 +3962,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { } else { xk = (tap->_klass_is_exact | this->_klass_is_exact); } - return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative); + return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative, depth); case Constant: { ciObject* o = const_oop(); if( _ptr == Constant ) { @@ -3889,7 +3981,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { // Only precise for identical arrays xk = this->_klass_is_exact && (klass() == tap->klass()); } - return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative); + return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative, depth); } case NotNull: case BotPTR: @@ -3898,7 +3990,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { xk = tap->_klass_is_exact; else xk = (tap->_klass_is_exact & this->_klass_is_exact) && (klass() == tap->klass()); // Only precise for identical arrays - return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative); + return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative, depth); default: ShouldNotReachHere(); } } @@ -3910,6 +4002,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3917,12 +4010,12 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { // below the centerline when the superclass is exact. We need to // do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { - return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); } case Constant: case NotNull: @@ -3937,7 +4030,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { // that is, my array type is a subtype of 'tp' klass return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } } // The other case cannot happen, since t cannot be a subtype of an array. @@ -3945,7 +4038,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); default: typerr(t); } } @@ -3956,7 +4049,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeAryPtr::xdual() const { - return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative()); + return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative(), dual_inline_depth()); } //----------------------interface_vs_oop--------------------------------------- @@ -4009,6 +4102,7 @@ void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } #endif @@ -4020,11 +4114,22 @@ bool TypeAryPtr::empty(void) const { //------------------------------add_offset------------------------------------- const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { - return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); + return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); } const Type *TypeAryPtr::remove_speculative() const { - return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL); + if (_speculative == NULL) { + return this; + } + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth); +} + +const TypeOopPtr *TypeAryPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, _speculative, depth); } //============================================================================= diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 8c30f69795e..fb58dc2f584 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -415,10 +415,15 @@ public: bool is_autobox_cache = false); // Speculative type. See TypeInstPtr + virtual const TypeOopPtr* speculative() const { return NULL; } virtual ciKlass* speculative_type() const { return NULL; } const Type* maybe_remove_speculative(bool include_speculative) const; virtual const Type* remove_speculative() const { return this; } + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { + return exact_kls != NULL; + } + private: // support arrays static const BasicType _basic_type[]; @@ -845,7 +850,7 @@ public: // Some kind of oop (Java pointer), either klass or instance or array. class TypeOopPtr : public TypePtr { protected: - TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); + TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -856,6 +861,10 @@ public: }; protected: + enum { + InlineDepthBottom = INT_MAX, + InlineDepthTop = -InlineDepthBottom + }; // Oop is NULL, unless this is a constant oop. ciObject* _const_oop; // Constant oop // If _klass is NULL, then so is _sig. This is an unloaded klass. @@ -876,6 +885,11 @@ protected: // use it, then we have to emit a guard: this part of the type is // not something we know but something we speculate about the type. const TypeOopPtr* _speculative; + // For speculative types, we record at what inlining depth the + // profiling point that provided the data is. We want to favor + // profile data coming from outer scopes which are likely better for + // the current compilation. + int _inline_depth; static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); @@ -891,6 +905,12 @@ protected: #ifndef PRODUCT void dump_speculative(outputStream *st) const; #endif + // utility methods to work on the inline depth of the type + int dual_inline_depth() const; + int meet_inline_depth(int depth) const; +#ifndef PRODUCT + void dump_inline_depth(outputStream *st) const; +#endif // Do not allow interface-vs.-noninterface joins to collapse to top. virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; @@ -921,7 +941,7 @@ public: bool not_null_elements = false); // Make a generic (unclassed) pointer to an oop. - static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative); + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); ciObject* const_oop() const { return _const_oop; } virtual ciKlass* klass() const { return _klass; } @@ -935,7 +955,7 @@ public: bool is_known_instance() const { return _instance_id > 0; } int instance_id() const { return _instance_id; } bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } - const TypeOopPtr* speculative() const { return _speculative; } + virtual const TypeOopPtr* speculative() const { return _speculative; } virtual intptr_t get_con() const; @@ -968,18 +988,23 @@ public: if (_speculative != NULL) { const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); if (speculative->klass_is_exact()) { - return speculative->klass(); + return speculative->klass(); } } return NULL; } + int inline_depth() const { + return _inline_depth; + } + virtual const TypeOopPtr* with_inline_depth(int depth) const; + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; }; //------------------------------TypeInstPtr------------------------------------ // Class of Java object pointers, pointing either to non-array Java instances // or to a Klass* (including array klasses). class TypeInstPtr : public TypeOopPtr { - TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); + TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1015,7 +1040,7 @@ class TypeInstPtr : public TypeOopPtr { } // Make a pointer to an oop. - static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); + static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); /** Create constant type for a constant boxed value */ const Type* get_const_boxed_value() const; @@ -1034,6 +1059,7 @@ class TypeInstPtr : public TypeOopPtr { virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part virtual const Type* remove_speculative() const; + virtual const TypeOopPtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1055,8 +1081,8 @@ class TypeInstPtr : public TypeOopPtr { // Class of Java array pointers class TypeAryPtr : public TypeOopPtr { TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, - int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative) - : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative), + int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth) + : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth), _ary(ary), _is_autobox_cache(is_autobox_cache) { @@ -1094,9 +1120,9 @@ public: bool is_autobox_cache() const { return _is_autobox_cache; } - static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); + static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); // Constant pointer to array - static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, bool is_autobox_cache = false); + static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false); // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; @@ -1112,6 +1138,7 @@ public: virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part virtual const Type* remove_speculative() const; + virtual const TypeOopPtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; From c5ab176b3e2c9db6931636d79598b42b4f657254 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 28 Feb 2014 18:27:14 +0000 Subject: [PATCH 234/265] 8035891: javac, rename method asFree() in InferenceContext to asUndetVar() which reflects better it's purpose Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Attr.java | 16 +++--- .../com/sun/tools/javac/comp/Infer.java | 52 ++++++++++--------- .../com/sun/tools/javac/comp/Resolve.java | 18 ++++--- 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index f7ae9d456d7..6090a579acb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -248,7 +248,7 @@ public class Attr extends JCTree.Visitor { if (!owntype.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) { if (allowPoly && inferenceContext.free(found)) { if ((ownkind & ~resultInfo.pkind) == 0) { - owntype = resultInfo.check(tree, inferenceContext.asFree(owntype)); + owntype = resultInfo.check(tree, inferenceContext.asUndetVar(owntype)); } else { log.error(tree.pos(), "unexpected.type", kindNames(resultInfo.pkind), @@ -2406,7 +2406,7 @@ public class Attr extends JCTree.Visitor { //add thrown types as bounds to the thrown types free variables if needed: if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) { List inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make); - List thrownTypes = resultInfo.checkContext.inferenceContext().asFree(lambdaType.getThrownTypes()); + List thrownTypes = resultInfo.checkContext.inferenceContext().asUndetVars(lambdaType.getThrownTypes()); chk.unhandled(inferredThrownTypes, thrownTypes); } @@ -2547,7 +2547,7 @@ public class Attr extends JCTree.Visitor { @Override public boolean compatible(Type found, Type req, Warner warn) { //return type must be compatible in both current context and assignment context - return chk.basicHandler.compatible(found, inferenceContext().asFree(req), warn); + return chk.basicHandler.compatible(found, inferenceContext().asUndetVar(req), warn); } @Override @@ -2580,7 +2580,7 @@ public class Attr extends JCTree.Visitor { * types must be compatible with the return type of the expected descriptor. */ private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) { - Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType()); + Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType()); //return values have already been checked - but if lambda has no return //values, we must ensure that void/value compatibility is correct; @@ -2592,7 +2592,7 @@ public class Attr extends JCTree.Visitor { diags.fragment("missing.ret.val", returnType))); } - List argTypes = checkContext.inferenceContext().asFree(descriptor.getParameterTypes()); + List argTypes = checkContext.inferenceContext().asUndetVars(descriptor.getParameterTypes()); if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) { checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); } @@ -2836,7 +2836,7 @@ public class Attr extends JCTree.Visitor { if (that.kind.isUnbound() && resultInfo.checkContext.inferenceContext().free(argtypes.head)) { //re-generate inference constraints for unbound receiver - if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asFree(argtypes.head), exprType)) { + if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asUndetVar(argtypes.head), exprType)) { //cannot happen as this has already been checked - we just need //to regenerate the inference constraints, as that has been lost //as a result of the call to inferenceContext.save() @@ -2874,7 +2874,7 @@ public class Attr extends JCTree.Visitor { @SuppressWarnings("fallthrough") void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) { - Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType()); + Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType()); Type resType; switch (tree.getMode()) { @@ -2906,7 +2906,7 @@ public class Attr extends JCTree.Visitor { } if (!speculativeAttr) { - List thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes()); + List thrownTypes = checkContext.inferenceContext().asUndetVars(descriptor.getThrownTypes()); if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) { log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes()); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 6e0a72d0739..7fa54fc374c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -219,9 +219,10 @@ public class Infer { */ Type generateReturnConstraints(Attr.ResultInfo resultInfo, MethodType mt, InferenceContext inferenceContext) { + InferenceContext rsInfoInfContext = resultInfo.checkContext.inferenceContext(); Type from = mt.getReturnType(); if (mt.getReturnType().containsAny(inferenceContext.inferencevars) && - resultInfo.checkContext.inferenceContext() != emptyContext) { + rsInfoInfContext != emptyContext) { from = types.capture(from); //add synthetic captured ivars for (Type t : from.getTypeArguments()) { @@ -230,13 +231,13 @@ public class Infer { } } } - Type qtype1 = inferenceContext.asFree(from); + Type qtype1 = inferenceContext.asUndetVar(from); Type to = returnConstraintTarget(qtype1, resultInfo.pt); - Assert.check(allowGraphInference || !resultInfo.checkContext.inferenceContext().free(to), + Assert.check(allowGraphInference || !rsInfoInfContext.free(to), "legacy inference engine cannot handle constraints on both sides of a subtyping assertion"); //we need to skip capture? Warner retWarn = new Warner(); - if (!resultInfo.checkContext.compatible(qtype1, resultInfo.checkContext.inferenceContext().asFree(to), retWarn) || + if (!resultInfo.checkContext.compatible(qtype1, rsInfoInfContext.asUndetVar(to), retWarn) || //unchecked conversion is not allowed in source 7 mode (!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) { throw inferenceException @@ -279,7 +280,7 @@ public class Infer { ListBuffer todo = new ListBuffer<>(); //step 1 - create fresh tvars for (Type t : vars) { - UndetVar uv = (UndetVar)inferenceContext.asFree(t); + UndetVar uv = (UndetVar)inferenceContext.asUndetVar(t); List upperBounds = uv.getBounds(InferenceBound.UPPER); if (Type.containsAny(upperBounds, vars)) { TypeSymbol fresh_tvar = new TypeVariableSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner); @@ -398,7 +399,7 @@ public class Infer { return types.createErrorType(funcInterface); } for (Type p : descParameterTypes) { - if (!types.isSameType(funcInterfaceContext.asFree(p), paramTypes.head)) { + if (!types.isSameType(funcInterfaceContext.asUndetVar(p), paramTypes.head)) { checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); return types.createErrorType(funcInterface); } @@ -532,22 +533,23 @@ public class Infer { if (uv.inst != null) { Type inst = uv.inst; for (Type u : uv.getBounds(InferenceBound.UPPER)) { - if (!isSubtype(inst, inferenceContext.asFree(u), warn, infer)) { + if (!isSubtype(inst, inferenceContext.asUndetVar(u), warn, infer)) { infer.reportBoundError(uv, BoundErrorKind.UPPER); } } for (Type l : uv.getBounds(InferenceBound.LOWER)) { - if (!isSubtype(inferenceContext.asFree(l), inst, warn, infer)) { + if (!isSubtype(inferenceContext.asUndetVar(l), inst, warn, infer)) { infer.reportBoundError(uv, BoundErrorKind.LOWER); } } for (Type e : uv.getBounds(InferenceBound.EQ)) { - if (!isSameType(inst, inferenceContext.asFree(e), infer)) { + if (!isSameType(inst, inferenceContext.asUndetVar(e), infer)) { infer.reportBoundError(uv, BoundErrorKind.EQ); } } } } + @Override boolean accepts(UndetVar uv, InferenceContext inferenceContext) { //applies to all undetvars @@ -599,12 +601,12 @@ public class Infer { for (Type e : uv.getBounds(InferenceBound.EQ)) { if (e.containsAny(inferenceContext.inferenceVars())) continue; for (Type u : uv.getBounds(InferenceBound.UPPER)) { - if (!isSubtype(e, inferenceContext.asFree(u), warn, infer)) { + if (!isSubtype(e, inferenceContext.asUndetVar(u), warn, infer)) { infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); } } for (Type l : uv.getBounds(InferenceBound.LOWER)) { - if (!isSubtype(inferenceContext.asFree(l), e, warn, infer)) { + if (!isSubtype(inferenceContext.asUndetVar(l), e, warn, infer)) { infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER); } } @@ -625,7 +627,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { - isSubtype(inferenceContext.asFree(b2), inferenceContext.asFree(b1), warn , infer); + isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn , infer); } } } @@ -646,7 +648,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { for (Type b2 : uv.getBounds(InferenceBound.EQ)) { - isSubtype(inferenceContext.asFree(b2), inferenceContext.asFree(b1), warn, infer); + isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer); } } } @@ -667,7 +669,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b1 : uv.getBounds(InferenceBound.EQ)) { for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { - isSubtype(inferenceContext.asFree(b2), inferenceContext.asFree(b1), warn, infer); + isSubtype(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), warn, infer); } } } @@ -689,7 +691,7 @@ public class Infer { for (Type b1 : uv.getBounds(InferenceBound.EQ)) { for (Type b2 : uv.getBounds(InferenceBound.EQ)) { if (b1 != b2) { - isSameType(inferenceContext.asFree(b2), inferenceContext.asFree(b1), infer); + isSameType(inferenceContext.asUndetVar(b2), inferenceContext.asUndetVar(b1), infer); } } } @@ -710,7 +712,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b : uv.getBounds(InferenceBound.UPPER)) { if (inferenceContext.inferenceVars().contains(b)) { - UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); if (uv2.isCaptured()) continue; //alpha <: beta //0. set beta :> alpha @@ -742,7 +744,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b : uv.getBounds(InferenceBound.LOWER)) { if (inferenceContext.inferenceVars().contains(b)) { - UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); if (uv2.isCaptured()) continue; //alpha :> beta //0. set beta <: alpha @@ -774,7 +776,7 @@ public class Infer { Infer infer = inferenceContext.infer(); for (Type b : uv.getBounds(InferenceBound.EQ)) { if (inferenceContext.inferenceVars().contains(b)) { - UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + UndetVar uv2 = (UndetVar)inferenceContext.asUndetVar(b); if (uv2.isCaptured()) continue; //alpha == beta //0. set beta == alpha @@ -1526,7 +1528,7 @@ public class Infer { StringBuilder buf = new StringBuilder(); String sep = ""; for (Type from : data) { - UndetVar uv = (UndetVar)inferenceContext.asFree(from); + UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from); for (Type bound : uv.getBounds(InferenceBound.values())) { if (bound.containsAny(List.from(to.data))) { buf.append(sep); @@ -1735,7 +1737,7 @@ public class Infer { Set optDepsByNode = stuckDeps.get(i); for (Node n_j : nodes) { Type j = n_j.data.first(); - UndetVar uv_i = (UndetVar)inferenceContext.asFree(i); + UndetVar uv_i = (UndetVar)inferenceContext.asUndetVar(i); if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) { //update i's bound dependencies n_i.addDependency(DependencyKind.BOUND, n_j); @@ -1883,6 +1885,8 @@ public class Infer { }); } + /* Returns the corresponding inference variables. + */ private List filterVars(Filter fu) { ListBuffer res = new ListBuffer<>(); for (Type t : undetvars) { @@ -1940,14 +1944,14 @@ public class Infer { * undet vars (used ahead of subtyping/compatibility checks to allow propagation * of inference constraints). */ - final Type asFree(Type t) { + final Type asUndetVar(Type t) { return types.subst(t, inferencevars, undetvars); } - final List asFree(List ts) { + final List asUndetVars(List ts) { ListBuffer buf = new ListBuffer<>(); for (Type t : ts) { - buf.append(asFree(t)); + buf.append(asUndetVar(t)); } return buf.toList(); } @@ -2123,7 +2127,7 @@ public class Infer { private boolean solveBasic(List varsToSolve, EnumSet steps) { boolean changed = false; for (Type t : varsToSolve.intersect(restvars())) { - UndetVar uv = (UndetVar)asFree(t); + UndetVar uv = (UndetVar)asUndetVar(t); for (InferenceStep step : steps) { if (step.accepts(uv, this)) { uv.inst = step.solve(uv, this); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index e3ea3cfe524..7771e6e45ad 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -898,7 +898,7 @@ public class Resolve { @Override public boolean compatible(Type found, Type req, Warner warn) { - found = pendingInferenceContext.asFree(found); + found = pendingInferenceContext.asUndetVar(found); req = infer.returnConstraintTarget(found, req); return super.compatible(found, req, warn); } @@ -935,8 +935,8 @@ public class Resolve { public boolean compatible(Type found, Type req, Warner warn) { return strict ? - types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req), warn) : - types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req), warn); + types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn) : + types.isConvertible(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn); } public void report(DiagnosticPosition pos, JCDiagnostic details) { @@ -1141,7 +1141,7 @@ public class Resolve { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); if (types.isSameTypes(desc_t.getParameterTypes(), - inferenceContext().asFree(desc_s.getParameterTypes()))) { + inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { if (types.asSuper(t, s.tsym) != null || types.asSuper(s, t.tsym) != null) { result &= MostSpecificCheckContext.super.compatible(t, s, warn); @@ -1168,7 +1168,7 @@ public class Resolve { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); if (types.isSameTypes(desc_t.getParameterTypes(), - inferenceContext().asFree(desc_s.getParameterTypes()))) { + inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { if (types.asSuper(t, s.tsym) != null || types.asSuper(s, t.tsym) != null) { result &= MostSpecificCheckContext.super.compatible(t, s, warn); @@ -3151,7 +3151,7 @@ public class Resolve { if (TreeInfo.isStaticSelector(referenceTree.expr, names) && argtypes.nonEmpty() && (argtypes.head.hasTag(NONE) || - types.isSubtypeUnchecked(inferenceContext.asFree(argtypes.head), site))) { + types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), site))) { return new UnboundMethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); } else { @@ -4263,7 +4263,11 @@ public class Resolve { } DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) { - return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext, pendingResult != null ? pendingResult.checkContext.deferredAttrContext() : deferredAttr.emptyDeferredAttrContext, warn); + DeferredAttrContext parent = (pendingResult == null) + ? deferredAttr.emptyDeferredAttrContext + : pendingResult.checkContext.deferredAttrContext(); + return deferredAttr.new DeferredAttrContext(attrMode, sym, step, + inferenceContext, parent, warn); } /** From 74250736aab9f1e29ef4783182858f28d639ae5a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 28 Feb 2014 20:25:24 +0100 Subject: [PATCH 235/265] 8031383: Error recovery in JavacParser could be improved Improving error recovery in JavacParser by avoiding artificial nextToken in JavacParser.reportSyntaxError. Co-authored-by: Dusan Balek Reviewed-by: jjg, jfranck --- .../sun/tools/javac/parser/JavacParser.java | 22 +++++++++++--- .../tools/javac/resources/compiler.properties | 3 ++ .../javac/TryWithResources/BadTwrSyntax.out | 7 +---- .../typeAnnotations/6967002/T6967002.out | 8 +---- .../failures/AnnotatedPackage2.out | 2 +- .../typeAnnotations/failures/OldArray.out | 10 ++----- .../diags/examples/ArrayAndReceiver.java | 3 -- .../diags/examples/EmptyCharLiteral.java | 1 - .../javac/diags/examples/IllegalDot.java | 2 -- .../diags/examples/IllegalStartOfType.java | 28 +++++++++++++++++ .../diags/examples/InitializerNotAllowed.java | 30 +++++++++++++++++++ .../diags/examples/InvalidBinaryNumber.java | 3 -- .../diags/examples/VarargsMustBeLast.java | 2 +- .../tools/javac/enum/EnumMembersOrder.out | 2 +- .../tools/javac/parser/7157165/T7157165.out | 4 +-- .../javac/parser/ErroneousParameters.java | 2 +- .../javac/parser/ErroneousParameters.out | 10 +------ .../javac/parser/MissingClosingBrace.java | 13 ++++++++ .../javac/parser/MissingClosingBrace.out | 2 ++ .../parser/SingleCommaAnnotationValueFail.out | 7 ++--- .../test/tools/javac/parser/T4881269.out | 6 +--- .../javac/processing/TestWarnErrorCount.java | 2 +- .../TestParseErrors/TestParseErrors.out | 7 +---- langtools/test/tools/javac/quid/T6999438.out | 6 +--- 24 files changed, 111 insertions(+), 71 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/IllegalStartOfType.java create mode 100644 langtools/test/tools/javac/diags/examples/InitializerNotAllowed.java create mode 100644 langtools/test/tools/javac/parser/MissingClosingBrace.java create mode 100644 langtools/test/tools/javac/parser/MissingClosingBrace.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 279f400baf4..aba1c7bc73a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -431,7 +431,9 @@ public class JavacParser implements Parser { return toP(err); } + private static final int RECOVERY_THRESHOLD = 50; private int errorPos = Position.NOPOS; + private int count = 0; /** * Report a syntax using the given the position parameter and arguments, @@ -456,9 +458,13 @@ public class JavacParser implements Parser { } } S.errPos(pos); - if (token.pos == errorPos) - nextToken(); // guarantee progress - errorPos = token.pos; + if (token.pos == errorPos) { + //check for a possible infinite loop in parsing: + Assert.check(count++ < RECOVERY_THRESHOLD); + } else { + count = 0; + errorPos = token.pos; + } } @@ -2288,14 +2294,19 @@ public class JavacParser implements Parser { @SuppressWarnings("fallthrough") List blockStatements() { //todo: skip to anchor on error(?) + int lastErrPos = -1; ListBuffer stats = new ListBuffer<>(); while (true) { List stat = blockStatement(); if (stat.isEmpty()) { return stats.toList(); } else { + // error recovery + if (token.pos == lastErrPos) + return stats.toList(); if (token.pos <= endPosTable.errorEndPos) { skip(false, true, true, true); + lastErrPos = token.pos; } stats.addAll(stat); } @@ -3424,9 +3435,12 @@ public class JavacParser implements Parser { token.kind == INTERFACE || allowEnums && token.kind == ENUM) { return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); - } else if (token.kind == LBRACE && !isInterface && + } else if (token.kind == LBRACE && (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && mods.annotations.isEmpty()) { + if (isInterface) { + error(token.pos, "initializer.not.allowed"); + } return List.of(block(pos, mods.flags)); } else { pos = token.pos; diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index a54e14afdc5..8ed68e04151 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1039,6 +1039,9 @@ compiler.err.unreachable.stmt=\ compiler.err.initializer.must.be.able.to.complete.normally=\ initializer must be able to complete normally +compiler.err.initializer.not.allowed=\ + initializers not allowed in interfaces + # 0: type compiler.err.unreported.exception.need.to.catch.or.throw=\ unreported exception {0}; must be caught or declared to be thrown diff --git a/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out index 1d182f8ba26..6733c8dce20 100644 --- a/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out +++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out @@ -1,7 +1,2 @@ BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.type -BadTwrSyntax.java:14:44: compiler.err.expected: = -BadTwrSyntax.java:14:45: compiler.err.expected: ')' -BadTwrSyntax.java:14:47: compiler.err.expected: '{' -BadTwrSyntax.java:15:19: compiler.err.illegal.start.of.expr -BadTwrSyntax.java:15:23: compiler.err.expected: ';' -6 errors +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out index 18b75307f04..f7e2685ff0a 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out +++ b/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out @@ -1,8 +1,2 @@ T6967002.java:33:22: compiler.err.expected: ')' -T6967002.java:33:25: compiler.err.illegal.start.of.expr -T6967002.java:33:28: compiler.err.illegal.start.of.expr -T6967002.java:33:29: compiler.err.illegal.start.of.expr -T6967002.java:33:27: compiler.err.not.stmt -T6967002.java:33:30: compiler.err.expected: ';' -T6967002.java:35:2: compiler.err.premature.eof -7 errors +1 error diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out index 2ab804500f8..77b25afc5e0 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out @@ -1,3 +1,3 @@ AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier -AnnotatedPackage2.java:9:10: compiler.err.expected3: class, interface, enum +AnnotatedPackage2.java:9:12: compiler.err.expected3: class, interface, enum 2 errors diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out index 6ae37b9ae1c..f6d3d0388a4 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out @@ -1,10 +1,4 @@ OldArray.java:12:11: compiler.err.expected: ']' OldArray.java:12:13: compiler.err.expected: token.identifier -OldArray.java:12:14: compiler.err.expected: ';' -OldArray.java:12:17: compiler.err.illegal.start.of.type -OldArray.java:12:18: compiler.err.expected: token.identifier -OldArray.java:12:19: compiler.err.expected: ';' -OldArray.java:12:22: compiler.err.illegal.start.of.type -OldArray.java:12:28: compiler.err.expected: token.identifier -OldArray.java:13:1: compiler.err.expected3: class, interface, enum -9 errors +OldArray.java:12:16: compiler.err.invalid.meth.decl.ret.type.req +3 errors diff --git a/langtools/test/tools/javac/diags/examples/ArrayAndReceiver.java b/langtools/test/tools/javac/diags/examples/ArrayAndReceiver.java index fc155973d52..d30aa67a545 100644 --- a/langtools/test/tools/javac/diags/examples/ArrayAndReceiver.java +++ b/langtools/test/tools/javac/diags/examples/ArrayAndReceiver.java @@ -22,9 +22,6 @@ */ // key: compiler.err.array.and.receiver -// key: compiler.err.expected -// key: compiler.err.expected3 -// key: compiler.err.illegal.start.of.type class ArrayAndReceiver { void m(ArrayAndReceiver this[]) { } diff --git a/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java b/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java index 28c40916715..e34ab6fc4d1 100644 --- a/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java +++ b/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java @@ -23,7 +23,6 @@ // key: compiler.err.empty.char.lit // key: compiler.err.unclosed.char.lit -// key: compiler.err.premature.eof class X { char c = ''; diff --git a/langtools/test/tools/javac/diags/examples/IllegalDot.java b/langtools/test/tools/javac/diags/examples/IllegalDot.java index be0aa4b6360..156b73dcf33 100644 --- a/langtools/test/tools/javac/diags/examples/IllegalDot.java +++ b/langtools/test/tools/javac/diags/examples/IllegalDot.java @@ -22,8 +22,6 @@ */ // key: compiler.err.illegal.dot -// key: compiler.err.expected -// key: compiler.err.illegal.start.of.type class X { void m(Object.. args) { } diff --git a/langtools/test/tools/javac/diags/examples/IllegalStartOfType.java b/langtools/test/tools/javac/diags/examples/IllegalStartOfType.java new file mode 100644 index 00000000000..10469b915dc --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IllegalStartOfType.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.illegal.start.of.type + +class IllegalStartOfType { + public void test(int i,) { } +} diff --git a/langtools/test/tools/javac/diags/examples/InitializerNotAllowed.java b/langtools/test/tools/javac/diags/examples/InitializerNotAllowed.java new file mode 100644 index 00000000000..526e89ff6d9 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/InitializerNotAllowed.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.initializer.not.allowed + +interface InitializerNotAllowed { + { + System.out.println(); + } +} diff --git a/langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java b/langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java index e7728e47d36..e591c2a9bae 100644 --- a/langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java +++ b/langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java @@ -22,9 +22,6 @@ */ // key: compiler.err.invalid.binary.number -// key: compiler.err.illegal.start.of.type -// key: compiler.err.expected -// key: compiler.err.premature.eof class InvalidBinaryNumber { int i = 0b201000010; diff --git a/langtools/test/tools/javac/diags/examples/VarargsMustBeLast.java b/langtools/test/tools/javac/diags/examples/VarargsMustBeLast.java index bff1fbb6fcb..0c728b99afd 100644 --- a/langtools/test/tools/javac/diags/examples/VarargsMustBeLast.java +++ b/langtools/test/tools/javac/diags/examples/VarargsMustBeLast.java @@ -23,6 +23,6 @@ // key: compiler.err.varargs.must.be.last -class VarargMustBeFinal { +class VarargMustBeLast { public void invalidVarArg(String... invalidVarArg, String extra) { } } diff --git a/langtools/test/tools/javac/enum/EnumMembersOrder.out b/langtools/test/tools/javac/enum/EnumMembersOrder.out index d89a3d72cae..75d17a7849b 100644 --- a/langtools/test/tools/javac/enum/EnumMembersOrder.out +++ b/langtools/test/tools/javac/enum/EnumMembersOrder.out @@ -1,6 +1,6 @@ EnumMembersOrder.java:11:16: compiler.err.expected: ')' EnumMembersOrder.java:11:17: compiler.err.expected3: ',', '}', ';' -EnumMembersOrder.java:11:19: compiler.err.expected: '}' +EnumMembersOrder.java:11:18: compiler.err.expected: '}' EnumMembersOrder.java:11:31: compiler.err.expected3: class, interface, enum EnumMembersOrder.java:17:13: compiler.err.expected3: class, interface, enum EnumMembersOrder.java:19:1: compiler.err.expected3: class, interface, enum diff --git a/langtools/test/tools/javac/parser/7157165/T7157165.out b/langtools/test/tools/javac/parser/7157165/T7157165.out index ed252dfd7e6..deb580df96c 100644 --- a/langtools/test/tools/javac/parser/7157165/T7157165.out +++ b/langtools/test/tools/javac/parser/7157165/T7157165.out @@ -1,4 +1,4 @@ T7157165.java:11:20: compiler.err.expected: > -T7157165.java:11:21: compiler.err.expected: ';' -T7157165.java:11:22: compiler.err.illegal.start.of.type +T7157165.java:11:22: compiler.err.expected: token.identifier +T7157165.java:11:28: compiler.err.expected: token.identifier 3 errors diff --git a/langtools/test/tools/javac/parser/ErroneousParameters.java b/langtools/test/tools/javac/parser/ErroneousParameters.java index f6311d6f2db..e2bc138c758 100644 --- a/langtools/test/tools/javac/parser/ErroneousParameters.java +++ b/langtools/test/tools/javac/parser/ErroneousParameters.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8030091 + * @bug 8030091 8031383 * @summary Producing reasonable errors for unexpected tokens in method parameters * @compile/fail/ref=ErroneousParameters.out -XDrawDiagnostics ErroneousParameters.java */ diff --git a/langtools/test/tools/javac/parser/ErroneousParameters.out b/langtools/test/tools/javac/parser/ErroneousParameters.out index 89d9e3743e6..638bbc080d3 100644 --- a/langtools/test/tools/javac/parser/ErroneousParameters.out +++ b/langtools/test/tools/javac/parser/ErroneousParameters.out @@ -1,14 +1,6 @@ ErroneousParameters.java:10:36: compiler.err.varargs.must.be.last ErroneousParameters.java:11:39: compiler.err.expected3: ',', ')', '[' -ErroneousParameters.java:11:42: compiler.err.illegal.start.of.type -ErroneousParameters.java:11:43: compiler.err.expected: token.identifier -ErroneousParameters.java:11:45: compiler.err.expected: ';' ErroneousParameters.java:12:40: compiler.err.illegal.start.of.type -ErroneousParameters.java:12:41: compiler.err.expected3: ',', ')', '[' -ErroneousParameters.java:12:43: compiler.err.expected: ';' ErroneousParameters.java:13:41: compiler.err.expected: ']' ErroneousParameters.java:14:38: compiler.err.expected3: ',', ')', '[' -ErroneousParameters.java:14:39: compiler.err.illegal.start.of.type -ErroneousParameters.java:14:40: compiler.err.expected: token.identifier -ErroneousParameters.java:14:42: compiler.err.expected: ';' -13 errors +5 errors diff --git a/langtools/test/tools/javac/parser/MissingClosingBrace.java b/langtools/test/tools/javac/parser/MissingClosingBrace.java new file mode 100644 index 00000000000..c28645ff042 --- /dev/null +++ b/langtools/test/tools/javac/parser/MissingClosingBrace.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8031383 + * @summary Verify that the parser handles a missing closing brace of a block gracefully. + * @compile/fail/ref=MissingClosingBrace.out -XDrawDiagnostics MissingClosingBrace.java + */ + +public class MissingClosingBrace { + private void test(int i) { + if (i > 0) { + + private int i; +} diff --git a/langtools/test/tools/javac/parser/MissingClosingBrace.out b/langtools/test/tools/javac/parser/MissingClosingBrace.out new file mode 100644 index 00000000000..b4eed3c5dc2 --- /dev/null +++ b/langtools/test/tools/javac/parser/MissingClosingBrace.out @@ -0,0 +1,2 @@ +MissingClosingBrace.java:12:5: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/parser/SingleCommaAnnotationValueFail.out b/langtools/test/tools/javac/parser/SingleCommaAnnotationValueFail.out index 10a8f4dce7c..8c8f0566d15 100644 --- a/langtools/test/tools/javac/parser/SingleCommaAnnotationValueFail.out +++ b/langtools/test/tools/javac/parser/SingleCommaAnnotationValueFail.out @@ -1,6 +1,3 @@ SingleCommaAnnotationValueFail.java:34:12: compiler.err.expected: '}' -SingleCommaAnnotationValueFail.java:34:13: compiler.err.illegal.start.of.type -SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected: token.identifier -SingleCommaAnnotationValueFail.java:34:15: compiler.err.expected: ';' -SingleCommaAnnotationValueFail.java:34:21: compiler.err.invalid.meth.decl.ret.type.req -5 errors +SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected3: class, interface, enum +2 errors diff --git a/langtools/test/tools/javac/parser/T4881269.out b/langtools/test/tools/javac/parser/T4881269.out index b6b26981096..b8436172ea7 100644 --- a/langtools/test/tools/javac/parser/T4881269.out +++ b/langtools/test/tools/javac/parser/T4881269.out @@ -2,8 +2,4 @@ T4881269.java:32:13: compiler.err.illegal.dot T4881269.java:33:27: compiler.err.illegal.dot T4881269.java:33:22: compiler.err.not.stmt T4881269.java:34:19: compiler.err.illegal.dot -T4881269.java:34:20: compiler.err.expected: ';' -T4881269.java:34:22: compiler.err.illegal.start.of.type -T4881269.java:34:23: compiler.err.expected: token.identifier -T4881269.java:34:25: compiler.err.expected: ';' -8 errors +4 errors diff --git a/langtools/test/tools/javac/processing/TestWarnErrorCount.java b/langtools/test/tools/javac/processing/TestWarnErrorCount.java index ceadf5fb735..c2ec5ecc5fe 100644 --- a/langtools/test/tools/javac/processing/TestWarnErrorCount.java +++ b/langtools/test/tools/javac/processing/TestWarnErrorCount.java @@ -214,7 +214,7 @@ public class TestWarnErrorCount extends JavacTestingAbstractProcessor { javaWarnsExpected = 0; break; case JAVA: - errsExpected = 2; + errsExpected = 1; msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1); javaWarnsExpected = 0; break; diff --git a/langtools/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out b/langtools/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out index 11cff7ddcf1..f84325eb93d 100644 --- a/langtools/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out +++ b/langtools/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out @@ -1,8 +1,3 @@ ParseErrors.java:37:37: compiler.err.expected: token.identifier ParseErrors.java:38:1: compiler.err.illegal.start.of.type -ParseErrors.java:38:2: compiler.err.expected3: ',', ')', '[' -ParseErrors.java:40:6: compiler.err.expected: ';' -ParseErrors.java:40:20: compiler.err.illegal.start.of.type -ParseErrors.java:41:5: compiler.err.expected: '(' -ParseErrors.java:41:8: compiler.err.expected: token.identifier -7 errors +2 errors diff --git a/langtools/test/tools/javac/quid/T6999438.out b/langtools/test/tools/javac/quid/T6999438.out index 3527ae6aa22..3a267eec2e0 100644 --- a/langtools/test/tools/javac/quid/T6999438.out +++ b/langtools/test/tools/javac/quid/T6999438.out @@ -1,6 +1,2 @@ T6999438.java:8:9: compiler.err.illegal.char: # -T6999438.java:8:10: compiler.err.illegal.start.of.type -T6999438.java:8:25: compiler.err.expected: token.identifier -T6999438.java:8:26: compiler.err.expected: ';' -T6999438.java:9:2: compiler.err.premature.eof -5 errors +1 error From 7ef1c32ad1a2e813635c200153d9cd54ccefd88b Mon Sep 17 00:00:00 2001 From: David Li Date: Fri, 28 Feb 2014 15:57:37 -0800 Subject: [PATCH 236/265] 8035469: Xerces Update: EncodingMap does not recognize Java-style encodings Cp1141-Cp1149 Reviewed-by: lancea, joehw --- .../xerces/internal/util/EncodingMap.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/util/EncodingMap.java b/jaxp/src/com/sun/org/apache/xerces/internal/util/EncodingMap.java index c4fe27e5144..8b083a3ba46 100644 --- a/jaxp/src/com/sun/org/apache/xerces/internal/util/EncodingMap.java +++ b/jaxp/src/com/sun/org/apache/xerces/internal/util/EncodingMap.java @@ -3,11 +3,12 @@ * DO NOT REMOVE OR ALTER! */ /* - * Copyright 1999-2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -469,6 +470,7 @@ import java.util.Hashtable; * @author TAMURA Kent, IBM * @author Andy Clark, IBM * + * @version $Id$ */ public class EncodingMap { @@ -907,16 +909,16 @@ public class EncodingMap { fJava2IANAMap.put("CP918", "EBCDIC-CP-AR2"); fJava2IANAMap.put("CP924", "IBM00924"); fJava2IANAMap.put("CP1026", "IBM1026"); - fJava2IANAMap.put("Cp01140", "IBM01140"); - fJava2IANAMap.put("Cp01141", "IBM01141"); - fJava2IANAMap.put("Cp01142", "IBM01142"); - fJava2IANAMap.put("Cp01143", "IBM01143"); - fJava2IANAMap.put("Cp01144", "IBM01144"); - fJava2IANAMap.put("Cp01145", "IBM01145"); - fJava2IANAMap.put("Cp01146", "IBM01146"); - fJava2IANAMap.put("Cp01147", "IBM01147"); - fJava2IANAMap.put("Cp01148", "IBM01148"); - fJava2IANAMap.put("Cp01149", "IBM01149"); + fJava2IANAMap.put("CP1140", "IBM01140"); + fJava2IANAMap.put("CP1141", "IBM01141"); + fJava2IANAMap.put("CP1142", "IBM01142"); + fJava2IANAMap.put("CP1143", "IBM01143"); + fJava2IANAMap.put("CP1144", "IBM01144"); + fJava2IANAMap.put("CP1145", "IBM01145"); + fJava2IANAMap.put("CP1146", "IBM01146"); + fJava2IANAMap.put("CP1147", "IBM01147"); + fJava2IANAMap.put("CP1148", "IBM01148"); + fJava2IANAMap.put("CP1149", "IBM01149"); fJava2IANAMap.put("EUCJIS", "EUC-JP"); fJava2IANAMap.put("KS_C_5601-1987", "KS_C_5601-1987"); fJava2IANAMap.put("GB2312", "GB2312"); From 3b5ca2458c65919434d3e54060b48e46f3861cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 3 Mar 2014 15:23:01 +0100 Subject: [PATCH 237/265] 8035948: Redesign property listeners for shared classes Reviewed-by: sundar, lagergren --- .../internal/tools/nasgen/ClassGenerator.java | 4 - .../tools/nasgen/ConstructorGenerator.java | 6 - .../tools/nasgen/PrototypeGenerator.java | 4 - .../tools/nasgen/StringConstants.java | 6 - .../internal/codegen/ConstantData.java | 49 ++- .../objects/AccessorPropertyDescriptor.java | 2 +- .../internal/objects/ArrayBufferView.java | 2 +- .../objects/DataPropertyDescriptor.java | 2 +- .../objects/GenericPropertyDescriptor.java | 2 +- .../jdk/nashorn/internal/objects/Global.java | 210 +--------- .../internal/objects/NativeArguments.java | 6 +- .../nashorn/internal/objects/NativeArray.java | 2 +- .../internal/objects/NativeArrayBuffer.java | 2 +- .../internal/objects/NativeBoolean.java | 2 +- .../nashorn/internal/objects/NativeDate.java | 2 +- .../nashorn/internal/objects/NativeDebug.java | 9 +- .../nashorn/internal/objects/NativeError.java | 2 +- .../internal/objects/NativeEvalError.java | 2 +- .../internal/objects/NativeJSAdapter.java | 10 +- .../internal/objects/NativeJavaImporter.java | 2 +- .../internal/objects/NativeNumber.java | 2 +- .../internal/objects/NativeRangeError.java | 2 +- .../objects/NativeReferenceError.java | 2 +- .../internal/objects/NativeRegExp.java | 2 +- .../objects/NativeRegExpExecResult.java | 2 +- .../objects/NativeStrictArguments.java | 6 +- .../internal/objects/NativeString.java | 2 +- .../internal/objects/NativeSyntaxError.java | 2 +- .../internal/objects/NativeTypeError.java | 2 +- .../internal/objects/NativeURIError.java | 2 +- .../internal/objects/PrototypeObject.java | 5 +- .../internal/objects/ScriptFunctionImpl.java | 32 +- .../internal/runtime/PropertyListener.java | 66 ---- .../runtime/PropertyListenerManager.java | 179 --------- .../internal/runtime/PropertyListeners.java | 222 +++++++++++ .../nashorn/internal/runtime/PropertyMap.java | 369 +++++++----------- .../RecompilableScriptFunctionData.java | 9 +- .../internal/runtime/ScriptFunction.java | 10 +- .../internal/runtime/ScriptFunctionData.java | 13 +- .../internal/runtime/ScriptObject.java | 113 +++--- .../internal/runtime/SetMethodCreator.java | 7 +- .../nashorn/internal/runtime/WithObject.java | 16 +- .../runtime/linker/NashornGuards.java | 19 +- .../src/jdk/nashorn/internal/scripts/JO.java | 2 +- 44 files changed, 592 insertions(+), 820 deletions(-) delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java create mode 100644 nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java index 69c28b29f53..bb6abbc0170 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java @@ -50,8 +50,6 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; @@ -191,8 +189,6 @@ public class ClassGenerator { // stack: Collection // pmap = PropertyMap.newMap(Collection); mi.invokeStatic(PROPERTYMAP_TYPE, PROPERTYMAP_NEWMAP, PROPERTYMAP_NEWMAP_DESC); - // pmap.setIsShared(); - mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_SETISSHARED, PROPERTYMAP_SETISSHARED_DESC); // $nasgenmap$ = pmap; mi.putStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC); mi.returnVoid(); diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java index d46f78c488b..67cbde44fdd 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java @@ -33,10 +33,7 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFF import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC; @@ -171,9 +168,6 @@ public class ConstructorGenerator extends ClassGenerator { private void loadMap(final MethodGenerator mi) { if (memberCount > 0) { mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC); - // make sure we use duplicated PropertyMap so that original map - // stays intact and so can be used for many globals. - mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC); } } diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java index 8bb1de5c588..7b1fff7607e 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java @@ -32,10 +32,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX; @@ -129,7 +126,6 @@ public class PrototypeGenerator extends ClassGenerator { mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC); // make sure we use duplicated PropertyMap so that original map // stays intact and so can be used for many global. - mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC); mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC); // initialize Function type fields initFunctionFields(mi); diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java index c4c1ab8d465..dd947033d34 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java @@ -45,11 +45,9 @@ import jdk.nashorn.internal.runtime.ScriptObject; @SuppressWarnings("javadoc") public interface StringConstants { // standard jdk types, methods - static final Type TYPE_METHOD = Type.getType(Method.class); static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); static final Type TYPE_OBJECT = Type.getType(Object.class); - static final Type TYPE_CLASS = Type.getType(Class.class); static final Type TYPE_STRING = Type.getType(String.class); static final Type TYPE_COLLECTION = Type.getType(Collection.class); static final Type TYPE_COLLECTIONS = Type.getType(Collections.class); @@ -104,10 +102,6 @@ public interface StringConstants { static final String PROPERTYMAP_DESC = TYPE_PROPERTYMAP.getDescriptor(); static final String PROPERTYMAP_NEWMAP = "newMap"; static final String PROPERTYMAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_COLLECTION); - static final String PROPERTYMAP_DUPLICATE = "duplicate"; - static final String PROPERTYMAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP); - static final String PROPERTYMAP_SETISSHARED = "setIsShared"; - static final String PROPERTYMAP_SETISSHARED_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP); // PrototypeObject static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName(); diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java index 631cdb3e3ea..292f1678bdf 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java @@ -25,6 +25,9 @@ package jdk.nashorn.internal.codegen; +import jdk.nashorn.internal.runtime.Property; +import jdk.nashorn.internal.runtime.PropertyMap; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -109,6 +112,43 @@ class ConstantData { } } + /** + * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals} + * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations + * from {@code java.lang.Object}. + */ + private static class PropertyMapWrapper { + private final PropertyMap propertyMap; + private final int hashCode; + + public PropertyMapWrapper(final PropertyMap map) { + int hash = 0; + for (final Property property : map.getProperties()) { + hash = hash << 7 ^ hash >> 7; + hash ^= property.hashCode(); + } + this.hashCode = hash; + this.propertyMap = map; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof PropertyMapWrapper)) { + return false; + } + + final Property[] ownProperties = propertyMap.getProperties(); + final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties(); + + return Arrays.equals(ownProperties, otherProperties); + } + } + /** * Constructor */ @@ -145,7 +185,14 @@ class ConstantData { * @return the index in the constant pool that the object was given */ public int add(final Object object) { - final Object entry = object.getClass().isArray() ? new ArrayWrapper(object) : object; + final Object entry; + if (object.getClass().isArray()) { + entry = new ArrayWrapper(object); + } else if (object instanceof PropertyMap) { + entry = new PropertyMapWrapper((PropertyMap) object); + } else { + entry = object; + } final Integer value = objectMap.get(entry); if (value != null) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java index 4d3fd43d32e..b3388eb0813 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java @@ -72,7 +72,7 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr } AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) { - super(global.getObjectPrototype(), global.getAccessorPropertyDescriptorMap()); + super(global.getObjectPrototype(), getInitialMap()); this.configurable = configurable; this.enumerable = enumerable; this.get = get; diff --git a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java index ecf8bec8b68..a7252fcc606 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java +++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java @@ -47,7 +47,7 @@ abstract class ArrayBufferView extends ScriptObject { } private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) { - super(global.getArrayBufferViewMap()); + super(getInitialMap()); checkConstructorArgs(buffer, byteOffset, elementLength); this.setProto(getPrototype(global)); this.setArray(factory().createArrayData(buffer, byteOffset, elementLength)); diff --git a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java index 39325627b2d..9f7d2e4f8e8 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java @@ -69,7 +69,7 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper } DataPropertyDescriptor(final boolean configurable, final boolean enumerable, final boolean writable, final Object value, final Global global) { - super(global.getObjectPrototype(), global.getDataPropertyDescriptorMap()); + super(global.getObjectPrototype(), getInitialMap()); this.configurable = configurable; this.enumerable = enumerable; this.writable = writable; diff --git a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java index 221fe002bcd..bfa06cb3b35 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java +++ b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java @@ -60,7 +60,7 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro } GenericPropertyDescriptor(final boolean configurable, final boolean enumerable, final Global global) { - super(global.getObjectPrototype(), global.getGenericPropertyDescriptorMap()); + super(global.getObjectPrototype(), getInitialMap()); this.configurable = configurable; this.enumerable = enumerable; } diff --git a/nashorn/src/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk/nashorn/internal/objects/Global.java index 819095c05e4..e8b12cb87cf 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java @@ -370,36 +370,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { */ private ScriptFunction typeErrorThrower; - private PropertyMap accessorPropertyDescriptorMap; - private PropertyMap arrayBufferViewMap; - private PropertyMap dataPropertyDescriptorMap; - private PropertyMap genericPropertyDescriptorMap; - private PropertyMap nativeArgumentsMap; - private PropertyMap nativeArrayMap; - private PropertyMap nativeArrayBufferMap; - private PropertyMap nativeBooleanMap; - private PropertyMap nativeDateMap; - private PropertyMap nativeErrorMap; - private PropertyMap nativeEvalErrorMap; - private PropertyMap nativeJSAdapterMap; - private PropertyMap nativeJavaImporterMap; - private PropertyMap nativeNumberMap; - private PropertyMap nativeRangeErrorMap; - private PropertyMap nativeReferenceErrorMap; - private PropertyMap nativeRegExpMap; - private PropertyMap nativeRegExpExecResultMap; - private PropertyMap nativeStrictArgumentsMap; - private PropertyMap nativeStringMap; - private PropertyMap nativeSyntaxErrorMap; - private PropertyMap nativeTypeErrorMap; - private PropertyMap nativeURIErrorMap; - private PropertyMap prototypeObjectMap; - private PropertyMap objectMap; - private PropertyMap functionMap; - private PropertyMap anonymousFunctionMap; - private PropertyMap strictFunctionMap; - private PropertyMap boundFunctionMap; - // Flag to indicate that a split method issued a return statement private int splitState = -1; @@ -557,7 +527,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { @Override public ScriptObject newObject() { - return new JO(getObjectPrototype(), getObjectMap()); + return new JO(getObjectPrototype(), JO.getInitialMap()); } @Override @@ -999,123 +969,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { return ScriptFunction.getPrototype(builtinFloat64Array); } - // Builtin PropertyMap accessors - PropertyMap getAccessorPropertyDescriptorMap() { - return accessorPropertyDescriptorMap; - } - - PropertyMap getArrayBufferViewMap() { - return arrayBufferViewMap; - } - - PropertyMap getDataPropertyDescriptorMap() { - return dataPropertyDescriptorMap; - } - - PropertyMap getGenericPropertyDescriptorMap() { - return genericPropertyDescriptorMap; - } - - PropertyMap getArgumentsMap() { - return nativeArgumentsMap; - } - - PropertyMap getArrayMap() { - return nativeArrayMap; - } - - PropertyMap getArrayBufferMap() { - return nativeArrayBufferMap; - } - - PropertyMap getBooleanMap() { - return nativeBooleanMap; - } - - PropertyMap getDateMap() { - return nativeDateMap; - } - - PropertyMap getErrorMap() { - return nativeErrorMap; - } - - PropertyMap getEvalErrorMap() { - return nativeEvalErrorMap; - } - - PropertyMap getJSAdapterMap() { - return nativeJSAdapterMap; - } - - PropertyMap getJavaImporterMap() { - return nativeJavaImporterMap; - } - - PropertyMap getNumberMap() { - return nativeNumberMap; - } - - PropertyMap getRangeErrorMap() { - return nativeRangeErrorMap; - } - - PropertyMap getReferenceErrorMap() { - return nativeReferenceErrorMap; - } - - PropertyMap getRegExpMap() { - return nativeRegExpMap; - } - - PropertyMap getRegExpExecResultMap() { - return nativeRegExpExecResultMap; - } - - PropertyMap getStrictArgumentsMap() { - return nativeStrictArgumentsMap; - } - - PropertyMap getStringMap() { - return nativeStringMap; - } - - PropertyMap getSyntaxErrorMap() { - return nativeSyntaxErrorMap; - } - - PropertyMap getTypeErrorMap() { - return nativeTypeErrorMap; - } - - PropertyMap getURIErrorMap() { - return nativeURIErrorMap; - } - - PropertyMap getPrototypeObjectMap() { - return prototypeObjectMap; - } - - PropertyMap getObjectMap() { - return objectMap; - } - - PropertyMap getFunctionMap() { - return functionMap; - } - - PropertyMap getAnonymousFunctionMap() { - return anonymousFunctionMap; - } - - PropertyMap getStrictFunctionMap() { - return strictFunctionMap; - } - - PropertyMap getBoundFunctionMap() { - return boundFunctionMap; - } - private ScriptFunction getBuiltinArray() { return builtinArray; } @@ -1631,14 +1484,11 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { final ScriptEnvironment env = getContext().getEnv(); - // duplicate PropertyMaps of Native* classes - copyInitialMaps(env); - // initialize Function and Object constructor initFunctionAndObject(); // Now fix Global's own proto. - this.setProto(getObjectPrototype()); + this.setInitialProto(getObjectPrototype()); // initialize global function properties this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); @@ -1783,7 +1633,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { final ScriptObject prototype = ScriptFunction.getPrototype(cons); prototype.set(NativeError.NAME, name, false); prototype.set(NativeError.MESSAGE, "", false); - prototype.setProto(errorProto); + prototype.setInitialProto(errorProto); return (ScriptFunction)cons; } @@ -1955,7 +1805,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { } if (res.getProto() == null) { - res.setProto(getObjectPrototype()); + res.setInitialProto(getObjectPrototype()); } return res; @@ -1965,46 +1815,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { } } - private void copyInitialMaps(final ScriptEnvironment env) { - this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate(); - this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate(); - this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate(); - this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate(); - this.nativeArrayMap = NativeArray.getInitialMap().duplicate(); - this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate(); - this.nativeDateMap = NativeDate.getInitialMap().duplicate(); - this.nativeErrorMap = NativeError.getInitialMap().duplicate(); - this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate(); - this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate(); - this.nativeNumberMap = NativeNumber.getInitialMap().duplicate(); - this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate(); - this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate(); - this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate(); - this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate(); - this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate(); - this.nativeStringMap = NativeString.getInitialMap().duplicate(); - this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate(); - this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate(); - this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate(); - this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate(); - this.objectMap = JO.getInitialMap().duplicate(); - this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate(); - this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate(); - this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate(); - this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate(); - - // java - if (! env._no_java) { - this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate(); - } - - // typed arrays - if (! env._no_typed_arrays) { - this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate(); - this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate(); - } - } - // Function and Object constructors are inter-dependent. Also, // Function.prototype // functions are not properly initialized. We fix the references here. @@ -2022,7 +1832,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { // Function.prototype === Object.getPrototypeOf(Function) === // - builtinFunction.setProto(anon); + builtinFunction.setInitialProto(anon); builtinFunction.setPrototype(anon); anon.set("constructor", builtinFunction, false); anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); @@ -2038,7 +1848,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { this.builtinObject = (ScriptFunction)initConstructor("Object"); final ScriptObject ObjectPrototype = getObjectPrototype(); // Object.getPrototypeOf(Function.prototype) === Object.prototype - anon.setProto(ObjectPrototype); + anon.setInitialProto(ObjectPrototype); // Function valued properties of Function.prototype were not properly // initialized. Because, these were created before global.function and @@ -2050,10 +1860,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { if (value instanceof ScriptFunction && value != anon) { final ScriptFunction func = (ScriptFunction)value; - func.setProto(getFunctionPrototype()); + func.setInitialProto(getFunctionPrototype()); final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { - prototype.setProto(ObjectPrototype); + prototype.setInitialProto(ObjectPrototype); } } } @@ -2068,7 +1878,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { final ScriptFunction func = (ScriptFunction)value; final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { - prototype.setProto(ObjectPrototype); + prototype.setInitialProto(ObjectPrototype); } } } @@ -2086,7 +1896,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { final ScriptFunction func = (ScriptFunction)value; final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { - prototype.setProto(ObjectPrototype); + prototype.setInitialProto(ObjectPrototype); } } } diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java index f85357326d4..03f68bf6cbb 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArguments.java @@ -68,7 +68,7 @@ public final class NativeArguments extends ScriptObject { final ArrayList properties = new ArrayList<>(2); properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH)); properties.add(AccessorProperty.create("callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE)); - map$ = PropertyMap.newMap(properties).setIsShared(); + map$ = PropertyMap.newMap(properties); } static PropertyMap getInitialMap() { @@ -267,9 +267,9 @@ public final class NativeArguments extends ScriptObject { final Global global = Global.instance(); final ScriptObject proto = global.getObjectPrototype(); if (isStrict) { - return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap()); + return new NativeStrictArguments(arguments, numParams, proto, NativeStrictArguments.getInitialMap()); } - return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap()); + return new NativeArguments(arguments, callee, numParams, proto, NativeArguments.getInitialMap()); } /** diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java index 67b9f1f1ed2..cc62d23cc1f 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java @@ -208,7 +208,7 @@ public final class NativeArray extends ScriptObject { } NativeArray(final ArrayData arrayData, final Global global) { - super(global.getArrayPrototype(), global.getArrayMap()); + super(global.getArrayPrototype(), getInitialMap()); this.setArray(arrayData); this.setIsArray(); } diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java index d75a2129afe..dbc1b24b2cb 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java @@ -57,7 +57,7 @@ final class NativeArrayBuffer extends ScriptObject { } protected NativeArrayBuffer(final byte[] byteArray, final Global global) { - super(global.getArrayBufferPrototype(), global.getArrayBufferMap()); + super(global.getArrayBufferPrototype(), getInitialMap()); this.buffer = byteArray; } diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java index bb57cc71a39..bd955079830 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java @@ -65,7 +65,7 @@ public final class NativeBoolean extends ScriptObject { } NativeBoolean(final boolean flag, final Global global) { - this(flag, global.getBooleanPrototype(), global.getBooleanMap()); + this(flag, global.getBooleanPrototype(), getInitialMap()); } NativeBoolean(final boolean flag) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java index 935285f02ad..b0d120222a9 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java @@ -127,7 +127,7 @@ public final class NativeDate extends ScriptObject { } NativeDate(final double time, final Global global) { - this(time, global.getDatePrototype(), global.getDateMap()); + this(time, global.getDatePrototype(), getInitialMap()); } private NativeDate (final double time) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java index 9ee7c99a7f7..59b7b2fe379 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java @@ -34,7 +34,7 @@ import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.objects.annotations.Where; import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.PropertyListenerManager; +import jdk.nashorn.internal.runtime.PropertyListeners; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; @@ -186,7 +186,7 @@ public final class NativeDebug extends ScriptObject { */ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object getListenerCount(final Object self, final Object obj) { - return (obj instanceof ScriptObject)? ((ScriptObject)obj).getListenerCount() : 0; + return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0; } /** @@ -203,14 +203,13 @@ public final class NativeDebug extends ScriptObject { out.println("ScriptObject count " + ScriptObject.getCount()); out.println("Scope count " + ScriptObject.getScopeCount()); - out.println("ScriptObject listeners added " + PropertyListenerManager.getListenersAdded()); - out.println("ScriptObject listeners removed " + PropertyListenerManager.getListenersRemoved()); + out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded()); + out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved()); out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount()); out.println("ScriptFunction invokes " + ScriptFunction.getInvokes()); out.println("ScriptFunction allocations " + ScriptFunction.getAllocations()); out.println("PropertyMap count " + PropertyMap.getCount()); out.println("PropertyMap cloned " + PropertyMap.getClonedCount()); - out.println("PropertyMap shared " + PropertyMap.getSharedCount()); out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount()); out.println("PropertyMap history hit " + PropertyMap.getHistoryHit()); out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations()); diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java index 0541084d8bf..e1a4730d553 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java @@ -108,7 +108,7 @@ public final class NativeError extends ScriptObject { } NativeError(final Object msg, final Global global) { - this(msg, global.getErrorPrototype(), global.getErrorMap()); + this(msg, global.getErrorPrototype(), getInitialMap()); } private NativeError(final Object msg) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java index df8164c1119..bb11ef6c354 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java @@ -78,7 +78,7 @@ public final class NativeEvalError extends ScriptObject { } NativeEvalError(final Object msg, final Global global) { - this(msg, global.getEvalErrorPrototype(), global.getEvalErrorMap()); + this(msg, global.getEvalErrorPrototype(), getInitialMap()); } private NativeEvalError(final Object msg) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java index 668ca8cd453..c77b2fe0fa9 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java @@ -163,7 +163,7 @@ public final class NativeJSAdapter extends ScriptObject { } private static ScriptObject wrapAdaptee(final ScriptObject adaptee) { - return new JO(adaptee, Global.instance().getObjectMap()); + return new JO(adaptee, JO.getInitialMap()); } @Override @@ -577,7 +577,7 @@ public final class NativeJSAdapter extends ScriptObject { proto = global.getJSAdapterPrototype(); } - return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, global.getJSAdapterMap()); + return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, getInitialMap()); } @Override @@ -629,7 +629,7 @@ public final class NativeJSAdapter extends ScriptObject { // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice. return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class, func.makeBoundFunction(this, new Object[] { name })), 0, Object.class), - adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), + adaptee.getProtoSwitchPoint(__call__, find.getOwner()), testJSAdaptor(adaptee, null, null, null)); } } @@ -700,7 +700,7 @@ public final class NativeJSAdapter extends ScriptObject { if (methodHandle != null) { return new GuardedInvocation( methodHandle, - adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), + adaptee.getProtoSwitchPoint(hook, findData.getOwner()), testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func)); } } @@ -713,7 +713,7 @@ public final class NativeJSAdapter extends ScriptObject { final MethodHandle methodHandle = hook.equals(__put__) ? MH.asType(Lookup.EMPTY_SETTER, type) : Lookup.emptyGetter(type.returnType()); - return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null)); + return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null)); } } diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java index 56baf66d229..c86f3053526 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java @@ -70,7 +70,7 @@ public final class NativeJavaImporter extends ScriptObject { } private NativeJavaImporter(final Object[] args, final Global global) { - this(args, global.getJavaImporterPrototype(), global.getJavaImporterMap()); + this(args, global.getJavaImporterPrototype(), getInitialMap()); } private NativeJavaImporter(final Object[] args) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java index d9d568b7e38..09289a015d0 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java @@ -98,7 +98,7 @@ public final class NativeNumber extends ScriptObject { } NativeNumber(final double value, final Global global) { - this(value, global.getNumberPrototype(), global.getNumberMap()); + this(value, global.getNumberPrototype(), getInitialMap()); } private NativeNumber(final double value) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java index a71b28b19c2..6e0d954bc7c 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java @@ -78,7 +78,7 @@ public final class NativeRangeError extends ScriptObject { } NativeRangeError(final Object msg, final Global global) { - this(msg, global.getRangeErrorPrototype(), global.getRangeErrorMap()); + this(msg, global.getRangeErrorPrototype(), getInitialMap()); } private NativeRangeError(final Object msg) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java index d02a325055b..052950c6d24 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java @@ -78,7 +78,7 @@ public final class NativeReferenceError extends ScriptObject { } NativeReferenceError(final Object msg, final Global global) { - this(msg, global.getReferenceErrorPrototype(), global.getReferenceErrorMap()); + this(msg, global.getReferenceErrorPrototype(), getInitialMap()); } private NativeReferenceError(final Object msg) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java index 318ca2a0edd..abc3366d353 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java @@ -75,7 +75,7 @@ public final class NativeRegExp extends ScriptObject { } private NativeRegExp(final Global global) { - super(global.getRegExpPrototype(), global.getRegExpMap()); + super(global.getRegExpPrototype(), getInitialMap()); this.globalObject = global; } diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java index 3508e5f67d1..5d79699e2ae 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java @@ -58,7 +58,7 @@ public final class NativeRegExpExecResult extends ScriptObject { } NativeRegExpExecResult(final RegExpResult result, final Global global) { - super(global.getArrayPrototype(), global.getRegExpExecResultMap()); + super(global.getArrayPrototype(), getInitialMap()); setIsArray(); this.setArray(ArrayData.allocate(result.getGroups().clone())); this.index = result.getIndex(); diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java index b81cc2afad4..dd2c2816c97 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java @@ -60,9 +60,9 @@ public final class NativeStrictArguments extends ScriptObject { // In strict mode, the caller and callee properties should throw TypeError // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; - map = map.addProperty(map.newUserAccessors("caller", flags)); - map = map.addProperty(map.newUserAccessors("callee", flags)); - map$ = map.setIsShared(); + map = map.addPropertyNoHistory(map.newUserAccessors("caller", flags)); + map = map.addPropertyNoHistory(map.newUserAccessors("callee", flags)); + map$ = map; } static PropertyMap getInitialMap() { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java index 95af71a6dd4..2370f514518 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java @@ -83,7 +83,7 @@ public final class NativeString extends ScriptObject { } NativeString(final CharSequence value, final Global global) { - this(value, global.getStringPrototype(), global.getStringMap()); + this(value, global.getStringPrototype(), getInitialMap()); } private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java index 5d71ade7d38..ffe1b0a7432 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java @@ -68,7 +68,7 @@ public final class NativeSyntaxError extends ScriptObject { @SuppressWarnings("LeakingThisInConstructor") NativeSyntaxError(final Object msg, final Global global) { - super(global.getSyntaxErrorPrototype(), global.getSyntaxErrorMap()); + super(global.getSyntaxErrorPrototype(), getInitialMap()); if (msg != UNDEFINED) { this.instMessage = JSType.toString(msg); } else { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java index 8857da7142d..067139cda3d 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java @@ -68,7 +68,7 @@ public final class NativeTypeError extends ScriptObject { @SuppressWarnings("LeakingThisInConstructor") NativeTypeError(final Object msg, final Global global) { - super(global.getTypeErrorPrototype(), global.getTypeErrorMap()); + super(global.getTypeErrorPrototype(), getInitialMap()); if (msg != UNDEFINED) { this.instMessage = JSType.toString(msg); } else { diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java index 7ff6c196e3f..382e23f4b65 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java @@ -67,7 +67,7 @@ public final class NativeURIError extends ScriptObject { @SuppressWarnings("LeakingThisInConstructor") NativeURIError(final Object msg, final Global global) { - super(global.getURIErrorPrototype(), global.getURIErrorMap()); + super(global.getURIErrorPrototype(), getInitialMap()); if (msg != UNDEFINED) { this.instMessage = JSType.toString(msg); } else { diff --git a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java index 4610afc2473..1fd4f60d5a0 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java +++ b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java @@ -54,7 +54,7 @@ public class PrototypeObject extends ScriptObject { static { final ArrayList properties = new ArrayList<>(1); properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR)); - map$ = PropertyMap.newMap(properties).setIsShared(); + map$ = PropertyMap.newMap(properties); } static PropertyMap getInitialMap() { @@ -62,8 +62,7 @@ public class PrototypeObject extends ScriptObject { } private PrototypeObject(final Global global, final PropertyMap map) { - super(map != map$? map.addAll(global.getPrototypeObjectMap()) : global.getPrototypeObjectMap()); - setProto(global.getObjectPrototype()); + super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$); } PrototypeObject() { diff --git a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java index f0bea3a6e33..9852c96273d 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java +++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java @@ -37,7 +37,6 @@ import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptFunctionData; import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.runtime.AccessorProperty; /** @@ -76,7 +75,7 @@ public class ScriptFunctionImpl extends ScriptFunction { private static final Object LAZY_PROTOTYPE = new Object(); private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { - super(name, invokeHandle, global.getFunctionMap(), null, specs, false, true, true); + super(name, invokeHandle, getInitialMap(), null, specs, false, true, true); init(global); } @@ -93,7 +92,7 @@ public class ScriptFunctionImpl extends ScriptFunction { } private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { - super(name, invokeHandle, map.addAll(global.getFunctionMap()), null, specs, false, true, true); + super(name, invokeHandle, map.addAll(getInitialMap()), null, specs, false, true, true); init(global); } @@ -151,7 +150,7 @@ public class ScriptFunctionImpl extends ScriptFunction { * @param global the global object */ ScriptFunctionImpl(final ScriptFunctionData data, final Global global) { - super(data, global.getBoundFunctionMap(), null); + super(data, getInitialBoundMap(), null); init(global); } @@ -163,25 +162,20 @@ public class ScriptFunctionImpl extends ScriptFunction { map$ = PropertyMap.newMap(properties); strictmodemap$ = createStrictModeMap(map$); boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); - // There are order dependencies between normal map, struct map and bound map - // We can make these 'shared' only after initialization of all three. - map$.setIsShared(); - strictmodemap$.setIsShared(); - boundfunctionmap$.setIsShared(); } private static PropertyMap createStrictModeMap(final PropertyMap map) { final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; PropertyMap newMap = map; // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. - newMap = newMap.addProperty(map.newUserAccessors("arguments", flags)); - newMap = newMap.addProperty(map.newUserAccessors("caller", flags)); + newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); + newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); return newMap; } // Choose the map based on strict mode! private static PropertyMap getMap(final Global global, final boolean strict) { - return strict ? global.getStrictFunctionMap() : global.getFunctionMap(); + return strict ? getInitialStrictMap() : getInitialMap(); } private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { @@ -193,14 +187,14 @@ public class ScriptFunctionImpl extends ScriptFunction { // Instance of this class is used as global anonymous function which // serves as Function.prototype object. private static class AnonymousFunction extends ScriptFunctionImpl { - private static final PropertyMap anonmap$ = PropertyMap.newMap().setIsShared(); + private static final PropertyMap anonmap$ = PropertyMap.newMap(); static PropertyMap getInitialMap() { return anonmap$; } AnonymousFunction(final Global global) { - super("", GlobalFunctions.ANONYMOUS, global.getAnonymousFunctionMap(), null); + super("", GlobalFunctions.ANONYMOUS, getInitialAnonymousMap(), null); } } @@ -281,13 +275,17 @@ public class ScriptFunctionImpl extends ScriptFunction { } @Override - public final void setPrototype(final Object prototype) { - this.prototype = prototype; + public final void setPrototype(final Object newProto) { + if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) { + // Replace our current allocator map with one that is associated with the new prototype. + allocatorMap = allocatorMap.changeProto((ScriptObject)newProto); + } + this.prototype = newProto; } // Internals below.. private void init(final Global global) { - this.setProto(global.getFunctionPrototype()); + this.setInitialProto(global.getFunctionPrototype()); this.prototype = LAZY_PROTOTYPE; // We have to fill user accessor functions late as these are stored diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java deleted file mode 100644 index 307d58b4f7d..00000000000 --- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.nashorn.internal.runtime; - -/** - * Property change listener gets notified whenever properties are added/deleted/modified. - */ -public interface PropertyListener { - /** - * A new property is being added. - * - * @param object The ScriptObject to which property was added. - * @param prop The new Property added. - */ - public void propertyAdded(ScriptObject object, Property prop); - - /** - * An existing property is being deleted. - * - * @param object The ScriptObject whose property is being deleted. - * @param prop The property being deleted. - */ - public void propertyDeleted(ScriptObject object, Property prop); - - /** - * An existing Property is being replaced with a new Property. - * - * @param object The ScriptObject whose property is being modified. - * @param oldProp The old property that is being replaced. - * @param newProp The new property that replaces the old property. - * - */ - public void propertyModified(ScriptObject object, Property oldProp, Property newProp); - - /** - * Given object's __proto__ has changed. - * - * @param object object whose __proto__ has changed. - * @param oldProto old __proto__ - * @param newProto new __proto__ - */ - public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto); -} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java deleted file mode 100644 index 27ec2c97438..00000000000 --- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.nashorn.internal.runtime; - -import java.util.Map; -import java.util.WeakHashMap; - -/** - * Helper class to manage property listeners and notification. - */ -public class PropertyListenerManager implements PropertyListener { - PropertyListenerManager() {} - - /** property listeners for this object. */ - private Map listeners; - - // These counters are updated in debug mode - private static int listenersAdded; - private static int listenersRemoved; - - /** - * Return aggregate listeners added to all PropertyListenerManagers - * @return the listenersAdded - */ - public static int getListenersAdded() { - return listenersAdded; - } - - /** - * Return aggregate listeners removed from all PropertyListenerManagers - * @return the listenersRemoved - */ - public static int getListenersRemoved() { - return listenersRemoved; - } - - /** - * Return listeners added to this PropertyListenerManager. - * @return the listener count - */ - public final int getListenerCount() { - return listeners != null? listeners.size() : 0; - } - - // Property listener management methods - - /** - * Add a property listener to this object. - * - * @param listener The property listener that is added. - */ - public synchronized final void addPropertyListener(final PropertyListener listener) { - if (listeners == null) { - listeners = new WeakHashMap<>(); - } - - if (Context.DEBUG) { - listenersAdded++; - } - listeners.put(listener, Boolean.TRUE); - } - - /** - * Remove a property listener from this object. - * - * @param listener The property listener that is removed. - */ - public synchronized final void removePropertyListener(final PropertyListener listener) { - if (listeners != null) { - if (Context.DEBUG) { - listenersRemoved++; - } - listeners.remove(listener); - } - } - - /** - * This method can be called to notify property addition to this object's listeners. - * - * @param object The ScriptObject to which property was added. - * @param prop The property being added. - */ - protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) { - if (listeners != null) { - for (PropertyListener listener : listeners.keySet()) { - listener.propertyAdded(object, prop); - } - } - } - - /** - * This method can be called to notify property deletion to this object's listeners. - * - * @param object The ScriptObject from which property was deleted. - * @param prop The property being deleted. - */ - protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) { - if (listeners != null) { - for (PropertyListener listener : listeners.keySet()) { - listener.propertyDeleted(object, prop); - } - } - } - - /** - * This method can be called to notify property modification to this object's listeners. - * - * @param object The ScriptObject to which property was modified. - * @param oldProp The old property being replaced. - * @param newProp The new property that replaces the old property. - */ - protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { - if (listeners != null) { - for (PropertyListener listener : listeners.keySet()) { - listener.propertyModified(object, oldProp, newProp); - } - } - } - - /** - * This method can be called to notify __proto__ modification to this object's listeners. - * - * @param object The ScriptObject whose __proto__ was changed. - * @param oldProto old __proto__ - * @param newProto new __proto__ - */ - protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) { - if (listeners != null) { - for (PropertyListener listener : listeners.keySet()) { - listener.protoChanged(object, oldProto, newProto); - } - } - } - - // PropertyListener methods - - @Override - public final void propertyAdded(final ScriptObject object, final Property prop) { - notifyPropertyAdded(object, prop); - } - - @Override - public final void propertyDeleted(final ScriptObject object, final Property prop) { - notifyPropertyDeleted(object, prop); - } - - @Override - public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { - notifyPropertyModified(object, oldProp, newProp); - } - - @Override - public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) { - notifyProtoChanged(object, oldProto, newProto); - } -} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java new file mode 100644 index 00000000000..532969ccce6 --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.nashorn.internal.runtime; + +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +/** + * Helper class to manage property listeners and notification. + */ +public class PropertyListeners { + + private Map listeners; + + // These counters are updated in debug mode + private static int listenersAdded; + private static int listenersRemoved; + + /** + * Copy constructor + * @param listener listener to copy + */ + PropertyListeners(final PropertyListeners listener) { + if (listener != null && listener.listeners != null) { + this.listeners = new WeakHashMap<>(listener.listeners); + } + } + + /** + * Return aggregate listeners added to all PropertyListenerManagers + * @return the listenersAdded + */ + public static int getListenersAdded() { + return listenersAdded; + } + + /** + * Return aggregate listeners removed from all PropertyListenerManagers + * @return the listenersRemoved + */ + public static int getListenersRemoved() { + return listenersRemoved; + } + + /** + * Return listeners added to this ScriptObject. + * @param obj the object + * @return the listener count + */ + public static int getListenerCount(final ScriptObject obj) { + final PropertyListeners propertyListeners = obj.getMap().getListeners(); + if (propertyListeners != null) { + return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size(); + } + return 0; + } + + // Property listener management methods + + /** + * Add {@code propertyMap} as property listener to {@code listeners} using key {@code key} by + * creating and returning a new {@code PropertyListeners} instance. + * + * @param listeners the original property listeners instance, may be null + * @param key the property key + * @param propertyMap the property map + * @return the new property map + */ + public static PropertyListeners addListener(final PropertyListeners listeners, final String key, final PropertyMap propertyMap) { + final PropertyListeners newListeners; + if (listeners == null || !listeners.containsListener(key, propertyMap)) { + newListeners = new PropertyListeners(listeners); + newListeners.addListener(key, propertyMap); + return newListeners; + } + return listeners; + } + + /** + * Checks whether {@code propertyMap} is registered as listener with {@code key}. + * + * @param key the property key + * @param propertyMap the property map + * @return true if property map is registered with property key + */ + synchronized boolean containsListener(final String key, final PropertyMap propertyMap) { + if (listeners == null) { + return false; + } + WeakPropertyMapSet set = listeners.get(key); + return set != null && set.contains(propertyMap); + } + + /** + * Add a property listener to this object. + * + * @param propertyMap The property listener that is added. + */ + synchronized final void addListener(final String key, final PropertyMap propertyMap) { + if (Context.DEBUG) { + listenersAdded++; + } + if (listeners == null) { + listeners = new WeakHashMap<>(); + } + + WeakPropertyMapSet set = listeners.get(key); + if (set == null) { + set = new WeakPropertyMapSet(); + listeners.put(key, set); + } + if (!set.contains(propertyMap)) { + set.add(propertyMap); + } + } + + /** + * A new property is being added. + * + * @param prop The new Property added. + */ + public synchronized void propertyAdded(final Property prop) { + if (listeners != null) { + WeakPropertyMapSet set = listeners.get(prop.getKey()); + if (set != null) { + for (PropertyMap propertyMap : set.elements()) { + propertyMap.propertyAdded(prop); + } + listeners.remove(prop.getKey()); + } + } + } + + /** + * An existing property is being deleted. + * + * @param prop The property being deleted. + */ + public synchronized void propertyDeleted(final Property prop) { + if (listeners != null) { + WeakPropertyMapSet set = listeners.get(prop.getKey()); + if (set != null) { + for (PropertyMap propertyMap : set.elements()) { + propertyMap.propertyDeleted(prop); + } + listeners.remove(prop.getKey()); + } + } + } + + /** + * An existing Property is being replaced with a new Property. + * + * @param oldProp The old property that is being replaced. + * @param newProp The new property that replaces the old property. + * + */ + public synchronized void propertyModified(final Property oldProp, final Property newProp) { + if (listeners != null) { + WeakPropertyMapSet set = listeners.get(oldProp.getKey()); + if (set != null) { + for (PropertyMap propertyMap : set.elements()) { + propertyMap.propertyModified(oldProp, newProp); + } + listeners.remove(oldProp.getKey()); + } + } + } + + public synchronized void protoChanged() { + if (listeners != null) { + for (WeakPropertyMapSet set : listeners.values()) { + for (PropertyMap propertyMap : set.elements()) { + propertyMap.protoChanged(); + } + } + listeners.clear(); + } + } + + private static class WeakPropertyMapSet { + + private WeakHashMap map = new WeakHashMap<>(); + + void add(final PropertyMap propertyMap) { + map.put(propertyMap, Boolean.TRUE); + } + + boolean contains(final PropertyMap propertyMap) { + return map.containsKey(propertyMap); + } + + Set elements() { + return map.keySet(); + } + + } +} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java index 03c4978aca6..77bcc83fea3 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java @@ -30,13 +30,11 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import java.lang.invoke.SwitchPoint; -import java.lang.ref.WeakReference; +import java.lang.ref.SoftReference; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.NoSuchElementException; import java.util.WeakHashMap; @@ -49,17 +47,11 @@ import java.util.WeakHashMap; * All property maps are immutable. If a property is added, modified or removed, the mutator * will return a new map. */ -public final class PropertyMap implements Iterable, PropertyListener { +public final class PropertyMap implements Iterable { /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */ public static final int NOT_EXTENSIBLE = 0b0000_0001; /** Does this map contain valid array keys? */ public static final int CONTAINS_ARRAY_KEYS = 0b0000_0010; - /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */ - private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111; - /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */ - public static final int IS_LISTENER_ADDED = 0b0001_0000; - /** Is this process wide "shared" map?. This flag is not copied when cloning a map */ - public static final int IS_SHARED = 0b0010_0000; /** Map status flags. */ private int flags; @@ -77,16 +69,16 @@ public final class PropertyMap implements Iterable, PropertyListener { private int spillLength; /** {@link SwitchPoint}s for gets on inherited properties. */ - private Map protoGetSwitches; + private HashMap protoGetSwitches; /** History of maps, used to limit map duplication. */ - private HashMap history; + private WeakHashMap> history; /** History of prototypes, used to limit map duplication. */ - private WeakHashMap> protoHistory; + private WeakHashMap> protoHistory; - /** Cache for hashCode */ - private int hashCode; + /** property listeners */ + private PropertyListeners listeners; /** * Constructor. @@ -119,10 +111,12 @@ public final class PropertyMap implements Iterable, PropertyListener { */ private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) { this.properties = properties; - this.flags = propertyMap.getClonedFlags(); + this.flags = propertyMap.flags; this.spillLength = propertyMap.spillLength; this.fieldCount = propertyMap.fieldCount; this.fieldMaximum = propertyMap.fieldMaximum; + // We inherit the parent property listeners instance. It will be cloned when a new listener is added. + this.listeners = propertyMap.listeners; if (Context.DEBUG) { count++; @@ -202,36 +196,93 @@ public final class PropertyMap implements Iterable, PropertyListener { return properties.size(); } + /** + * Get the listeners of this map, or null if none exists + * + * @return the listeners + */ + public PropertyListeners getListeners() { + return listeners; + } + + /** + * Add {@code listenerMap} as a listener to this property map for the given {@code key}. + * + * @param key the property name + * @param listenerMap the listener map + */ + public void addListener(final String key, final PropertyMap listenerMap) { + if (listenerMap != this) { + // We need to clone listener instance when adding a new listener since we share + // the listeners instance with our parent maps that don't need to see the new listener. + listeners = PropertyListeners.addListener(listeners, key, listenerMap); + } + } + + /** + * A new property is being added. + * + * @param property The new Property added. + */ + public void propertyAdded(final Property property) { + invalidateProtoGetSwitchPoint(property); + if (listeners != null) { + listeners.propertyAdded(property); + } + } + + /** + * An existing property is being deleted. + * + * @param property The property being deleted. + */ + public void propertyDeleted(final Property property) { + invalidateProtoGetSwitchPoint(property); + if (listeners != null) { + listeners.propertyDeleted(property); + } + } + + /** + * An existing property is being redefined. + * + * @param oldProperty The old property + * @param newProperty The new property + */ + public void propertyModified(final Property oldProperty, final Property newProperty) { + invalidateProtoGetSwitchPoint(oldProperty); + if (listeners != null) { + listeners.propertyModified(oldProperty, newProperty); + } + } + + /** + * The prototype of an object associated with this {@link PropertyMap} is changed. + */ + public void protoChanged() { + invalidateAllProtoGetSwitchPoints(); + if (listeners != null) { + listeners.protoChanged(); + } + } + /** * Return a SwitchPoint used to track changes of a property in a prototype. * - * @param proto Object prototype. - * @param key {@link Property} key. - * + * @param key Property key. * @return A shared {@link SwitchPoint} for the property. */ - public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) { - assert !isShared() : "proto SwitchPoint from a shared PropertyMap"; - - if (proto == null) { - return null; - } - + public synchronized SwitchPoint getSwitchPoint(final String key) { if (protoGetSwitches == null) { protoGetSwitches = new HashMap<>(); - if (! isListenerAdded()) { - proto.addPropertyListener(this); - setIsListenerAdded(); - } } - if (protoGetSwitches.containsKey(key)) { - return protoGetSwitches.get(key); + SwitchPoint switchPoint = protoGetSwitches.get(key); + if (switchPoint == null) { + switchPoint = new SwitchPoint(); + protoGetSwitches.put(key, switchPoint); } - final SwitchPoint switchPoint = new SwitchPoint(); - protoGetSwitches.put(key, switchPoint); - return switchPoint; } @@ -240,14 +291,13 @@ public final class PropertyMap implements Iterable, PropertyListener { * * @param property {@link Property} to invalidate. */ - private void invalidateProtoGetSwitchPoint(final Property property) { - assert !isShared() : "proto invalidation on a shared PropertyMap"; - + synchronized void invalidateProtoGetSwitchPoint(final Property property) { if (protoGetSwitches != null) { + final String key = property.getKey(); final SwitchPoint sp = protoGetSwitches.get(key); if (sp != null) { - protoGetSwitches.put(key, new SwitchPoint()); + protoGetSwitches.remove(key); if (Context.DEBUG) { protoInvalidations++; } @@ -257,14 +307,15 @@ public final class PropertyMap implements Iterable, PropertyListener { } /** - * Indicate that proto itself has changed in hierachy somewhere. + * Indicate that proto itself has changed in hierarchy somewhere. */ - private void invalidateAllProtoGetSwitchPoints() { - assert !isShared() : "proto invalidation on a shared PropertyMap"; - - if (protoGetSwitches != null) { - final Collection sws = protoGetSwitches.values(); - SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()])); + synchronized void invalidateAllProtoGetSwitchPoints() { + if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) { + if (Context.DEBUG) { + protoInvalidations += protoGetSwitches.size(); + } + SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()])); + protoGetSwitches.clear(); } } @@ -279,7 +330,33 @@ public final class PropertyMap implements Iterable, PropertyListener { * @return New {@link PropertyMap} with {@link Property} added. */ PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) { - return addProperty(new AccessorProperty(property, bindTo)); + // No need to store bound property in the history as bound properties can't be reused. + return addPropertyNoHistory(new AccessorProperty(property, bindTo)); + } + + /** + * Add a property to the map without adding it to the history. This should be used for properties that + * can't be shared such as bound properties, or properties that are expected to be added only once. + * + * @param property {@link Property} being added. + * @return New {@link PropertyMap} with {@link Property} added. + */ + public PropertyMap addPropertyNoHistory(final Property property) { + if (listeners != null) { + listeners.propertyAdded(property); + } + final PropertyHashMap newProperties = properties.immutableAdd(property); + final PropertyMap newMap = new PropertyMap(this, newProperties); + + if(!property.isSpill()) { + newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1); + } + if (isValidArrayIndex(getArrayIndex(property.getKey()))) { + newMap.setContainsArrayKeys(); + } + + newMap.spillLength += property.getSpillCount(); + return newMap; } /** @@ -290,6 +367,9 @@ public final class PropertyMap implements Iterable, PropertyListener { * @return New {@link PropertyMap} with {@link Property} added. */ public PropertyMap addProperty(final Property property) { + if (listeners != null) { + listeners.propertyAdded(property); + } PropertyMap newMap = checkHistory(property); if (newMap == null) { @@ -318,6 +398,9 @@ public final class PropertyMap implements Iterable, PropertyListener { * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found. */ public PropertyMap deleteProperty(final Property property) { + if (listeners != null) { + listeners.propertyDeleted(property); + } PropertyMap newMap = checkHistory(property); final String key = property.getKey(); @@ -339,6 +422,9 @@ public final class PropertyMap implements Iterable, PropertyListener { * @return New {@link PropertyMap} with {@link Property} replaced. */ PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) { + if (listeners != null) { + listeners.propertyModified(oldProperty, newProperty); + } // Add replaces existing property. final PropertyHashMap newProperties = properties.immutableAdd(newProperty); final PropertyMap newMap = new PropertyMap(this, newProperties); @@ -363,7 +449,7 @@ public final class PropertyMap implements Iterable, PropertyListener { (oldProperty instanceof AccessorProperty && newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted"; - newMap.flags = getClonedFlags(); + newMap.flags = flags; /* * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need @@ -490,28 +576,6 @@ public final class PropertyMap implements Iterable, PropertyListener { return newMap; } - /** - * Make this property map 'shared' one. Shared property map instances are - * process wide singleton objects. A shaped map should never be added as a listener - * to a proto object. Nor it should have history or proto history. A shared map - * is just a template that is meant to be duplicated before use. All nasgen initialized - * property maps are shared. - * - * @return this map after making it as shared - */ - public PropertyMap setIsShared() { - assert !isListenerAdded() : "making PropertyMap shared after listener added"; - assert protoHistory == null : "making PropertyMap shared after associating a proto with it"; - if (Context.DEBUG) { - sharedCount++; - } - - flags |= IS_SHARED; - // clear any history on this PropertyMap, won't be used. - history = null; - return this; - } - /** * Check for any configurable properties. * @@ -551,14 +615,14 @@ public final class PropertyMap implements Iterable, PropertyListener { /** * Check prototype history for an existing property map with specified prototype. * - * @param newProto New prototype object. + * @param parentMap New prototype object. * * @return Existing {@link PropertyMap} or {@code null} if not found. */ - private PropertyMap checkProtoHistory(final ScriptObject newProto) { + private PropertyMap checkProtoHistory(final PropertyMap parentMap) { final PropertyMap cachedMap; if (protoHistory != null) { - final WeakReference weakMap = protoHistory.get(newProto); + final SoftReference weakMap = protoHistory.get(parentMap); cachedMap = (weakMap != null ? weakMap.get() : null); } else { cachedMap = null; @@ -574,17 +638,15 @@ public final class PropertyMap implements Iterable, PropertyListener { /** * Add a map to the prototype history. * - * @param newProto Prototype to add (key.) + * @param parentMap Prototype to add (key.) * @param newMap {@link PropertyMap} associated with prototype. */ - private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) { - assert !isShared() : "proto history modified on a shared PropertyMap"; - + private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) { if (protoHistory == null) { protoHistory = new WeakHashMap<>(); } - protoHistory.put(newProto, new WeakReference<>(newMap)); + protoHistory.put(parentMap, new SoftReference<>(newMap)); } /** @@ -594,14 +656,12 @@ public final class PropertyMap implements Iterable, PropertyListener { * @param newMap Modified {@link PropertyMap}. */ private void addToHistory(final Property property, final PropertyMap newMap) { - assert !isShared() : "history modified on a shared PropertyMap"; - if (!properties.isEmpty()) { if (history == null) { - history = new LinkedHashMap<>(); + history = new WeakHashMap<>(); } - history.put(property, newMap); + history.put(property, new SoftReference<>(newMap)); } } @@ -613,8 +673,10 @@ public final class PropertyMap implements Iterable, PropertyListener { * @return Existing map or {@code null} if not found. */ private PropertyMap checkHistory(final Property property) { + if (history != null) { - PropertyMap historicMap = history.get(property); + SoftReference ref = history.get(property); + final PropertyMap historicMap = ref == null ? null : ref.get(); if (historicMap != null) { if (Context.DEBUG) { @@ -628,54 +690,6 @@ public final class PropertyMap implements Iterable, PropertyListener { return null; } - /** - * Calculate the hash code for the map. - * - * @return Computed hash code. - */ - private int computeHashCode() { - int hash = 0; - - for (final Property property : getProperties()) { - hash = hash << 7 ^ hash >> 7; - hash ^= property.hashCode(); - } - - return hash; - } - - @Override - public int hashCode() { - if (hashCode == 0 && !properties.isEmpty()) { - hashCode = computeHashCode(); - } - return hashCode; - } - - @Override - public boolean equals(final Object other) { - if (!(other instanceof PropertyMap)) { - return false; - } - - final PropertyMap otherMap = (PropertyMap)other; - - if (properties.size() != otherMap.properties.size()) { - return false; - } - - final Iterator iter = properties.values().iterator(); - final Iterator otherIter = otherMap.properties.values().iterator(); - - while (iter.hasNext() && otherIter.hasNext()) { - if (!iter.next().equals(otherIter.next())) { - return false; - } - } - - return true; - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -727,24 +741,6 @@ public final class PropertyMap implements Iterable, PropertyListener { flags |= CONTAINS_ARRAY_KEYS; } - /** - * Check whether a {@link PropertyListener} has been added to this map. - * - * @return {@code true} if {@link PropertyListener} exists - */ - public boolean isListenerAdded() { - return (flags & IS_LISTENER_ADDED) != 0; - } - - /** - * Check if this map shared or not. - * - * @return true if this map is shared. - */ - public boolean isShared() { - return (flags & IS_SHARED) != 0; - } - /** * Test to see if {@link PropertyMap} is extensible. * @@ -800,50 +796,29 @@ public final class PropertyMap implements Iterable, PropertyListener { } /** - * Change the prototype of objects associated with this {@link PropertyMap}. + * Return a property map with the same layout that is associated with the new prototype object. * - * @param oldProto Current prototype object. * @param newProto New prototype object to replace oldProto. - * * @return New {@link PropertyMap} with prototype changed. */ - PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) { - assert !isShared() : "proto associated with a shared PropertyMap"; + public PropertyMap changeProto(final ScriptObject newProto) { - if (oldProto == newProto) { - return this; - } - - final PropertyMap nextMap = checkProtoHistory(newProto); + final PropertyMap parentMap = newProto == null ? null : newProto.getMap(); + final PropertyMap nextMap = checkProtoHistory(parentMap); if (nextMap != null) { return nextMap; } if (Context.DEBUG) { - incrementSetProtoNewMapCount(); + setProtoNewMapCount++; } final PropertyMap newMap = new PropertyMap(this); - addToProtoHistory(newProto, newMap); + addToProtoHistory(parentMap, newMap); return newMap; } - /** - * Indicate that the map has listeners. - */ - private void setIsListenerAdded() { - flags |= IS_LISTENER_ADDED; - } - - /** - * Return only the flags that should be copied during cloning. - * - * @return Subset of flags that should be copied. - */ - private int getClonedFlags() { - return flags & CLONEABLE_FLAGS_MASK; - } /** * {@link PropertyMap} iterator. @@ -899,34 +874,6 @@ public final class PropertyMap implements Iterable, PropertyListener { } } - /* - * PropertyListener implementation. - */ - - @Override - public void propertyAdded(final ScriptObject object, final Property prop) { - invalidateProtoGetSwitchPoint(prop); - } - - @Override - public void propertyDeleted(final ScriptObject object, final Property prop) { - invalidateProtoGetSwitchPoint(prop); - } - - @Override - public void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { - invalidateProtoGetSwitchPoint(oldProp); - } - - @Override - public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) { - // We may walk and invalidate SwitchPoints for properties inherited - // from 'object' or it's old proto chain. But, it may not be worth it. - // For example, a new proto may have a user defined getter/setter for - // a data property down the chain. So, invalidating all is better. - invalidateAllProtoGetSwitchPoints(); - } - /* * Debugging and statistics. */ @@ -934,7 +881,6 @@ public final class PropertyMap implements Iterable, PropertyListener { // counters updated only in debug mode private static int count; private static int clonedCount; - private static int sharedCount; private static int duplicatedCount; private static int historyHit; private static int protoInvalidations; @@ -955,13 +901,6 @@ public final class PropertyMap implements Iterable, PropertyListener { return clonedCount; } - /** - * @return The number of maps that are shared. - */ - public static int getSharedCount() { - return sharedCount; - } - /** * @return The number of maps that are duplicated. */ @@ -997,10 +936,4 @@ public final class PropertyMap implements Iterable, PropertyListener { return setProtoNewMapCount; } - /** - * Increment the prototype set count. - */ - private static void incrementSetProtoNewMapCount() { - setProtoNewMapCount++; - } } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java index e5ca3c9a603..2b18cbc87b6 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java @@ -160,10 +160,10 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData { } @Override - ScriptObject allocate() { + ScriptObject allocate(final PropertyMap map) { try { ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try - return allocator == null ? null : (ScriptObject)allocator.invokeExact(allocatorMap); + return allocator == null ? null : (ScriptObject)allocator.invokeExact(map); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -177,6 +177,11 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData { } } + @Override + PropertyMap getAllocatorMap() { + return allocatorMap; + } + @Override protected synchronized void ensureCodeGenerated() { if (!code.isEmpty()) { diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java index d0669d709de..0f5174ea15b 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java @@ -80,6 +80,9 @@ public abstract class ScriptFunction extends ScriptObject { private final ScriptFunctionData data; + /** The property map used for newly allocated object when function is used as constructor. */ + protected PropertyMap allocatorMap; + /** * Constructor * @@ -125,6 +128,7 @@ public abstract class ScriptFunction extends ScriptObject { this.data = data; this.scope = scope; + this.allocatorMap = data.getAllocatorMap(); } @Override @@ -229,16 +233,16 @@ public abstract class ScriptFunction extends ScriptObject { } assert !isBoundFunction(); // allocate never invoked on bound functions - final ScriptObject object = data.allocate(); + final ScriptObject object = data.allocate(allocatorMap); if (object != null) { Object prototype = getPrototype(); if (prototype instanceof ScriptObject) { - object.setProto((ScriptObject)prototype); + object.setInitialProto((ScriptObject)prototype); } if (object.getProto() == null) { - object.setProto(getObjectPrototype()); + object.setInitialProto(getObjectPrototype()); } } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java index 4dbbfba996d..f0569937dd0 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java @@ -229,9 +229,20 @@ public abstract class ScriptFunctionData { /** * Allocates an object using this function's allocator. + * + * @param map the property map for the allocated object. * @return the object allocated using this function's allocator, or null if the function doesn't have an allocator. */ - ScriptObject allocate() { + ScriptObject allocate(final PropertyMap map) { + return null; + } + + /** + * Get the property map to use for objects allocated by this function. + * + * @return the property map for allocated objects. + */ + PropertyMap getAllocatorMap() { return null; } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java index 4b3bb939411..b7f9c4c1ed0 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -43,6 +43,7 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.invoke.SwitchPoint; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; @@ -88,7 +89,7 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards; * */ -public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess { +public abstract class ScriptObject implements PropertyAccess { /** __proto__ special property name */ public static final String PROTO_PROPERTY_NAME = "__proto__"; @@ -107,9 +108,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr /** Per ScriptObject flag - is this an arguments object? */ public static final int IS_ARGUMENTS = 0b0000_0100; - /** Is this a prototype PropertyMap? */ - public static final int IS_PROTOTYPE = 0b0000_1000; - /** Is length property not-writable? */ public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000; @@ -155,7 +153,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class); /** Method handle for setting the proto of a ScriptObject */ - public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class); + public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class); /** Method handle for setting the proto of a ScriptObject after checking argument */ public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class); @@ -201,10 +199,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr this.arrayData = ArrayData.EMPTY_ARRAY; this.setMap(map == null ? PropertyMap.newMap() : map); this.proto = proto; - - if (proto != null) { - proto.setIsPrototype(); - } } /** @@ -232,7 +226,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr if (oldProp == null) { if (property instanceof UserAccessorProperty) { final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source)); - newMap = newMap.addProperty(prop); + newMap = newMap.addPropertyNoHistory(prop); } else { newMap = newMap.addPropertyBind((AccessorProperty)property, source); } @@ -875,8 +869,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter); } - notifyPropertyModified(this, oldProperty, newProperty); - return modifyOwnProperty(oldProperty, newProperty); } @@ -1120,28 +1112,32 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr */ public synchronized final void setProto(final ScriptObject newProto) { final ScriptObject oldProto = proto; - map = map.changeProto(oldProto, newProto); - if (newProto != null) { - newProto.setIsPrototype(); - } + if (oldProto != newProto) { + proto = newProto; - proto = newProto; - - if (isPrototype()) { - // tell listeners that my __proto__ has been changed - notifyProtoChanged(this, oldProto, newProto); - - if (oldProto != null) { - oldProto.removePropertyListener(this); - } - - if (newProto != null) { - newProto.addPropertyListener(this); + // Let current listeners know that the protototype has changed and set our map + final PropertyListeners listeners = getMap().getListeners(); + if (listeners != null) { + listeners.protoChanged(); } + // Replace our current allocator map with one that is associated with the new prototype. + setMap(getMap().changeProto(newProto)); } } + /** + * Set the initial __proto__ of this object. This should be used instead of + * {@link #setProto} if it is known that the current property map will not be + * used on a new object with any other parent property map, so we can pass over + * property map invalidation/evolution. + * + * @param initialProto the initial __proto__ to set. + */ + public void setInitialProto(final ScriptObject initialProto) { + this.proto = initialProto; + } + /** * Set the __proto__ of an object with checks. * @param newProto Prototype to set. @@ -1331,25 +1327,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr flags |= IS_ARGUMENTS; } - /** - * Check if this object is a prototype - * - * @return {@code true} if is prototype - */ - public final boolean isPrototype() { - return (flags & IS_PROTOTYPE) != 0; - } - - /** - * Flag this object as having a prototype. - */ - public final void setIsPrototype() { - if (proto != null && !isPrototype()) { - proto.addPropertyListener(this); - } - flags |= IS_PROTOTYPE; - } - /** * Check if this object has non-writable length property * @@ -1791,6 +1768,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr final boolean noGuard = ObjectClassGenerator.OBJECT_FIELDS_ONLY && NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType(); // getMap() is fine as we have the prototype switchpoint depending on where the property was found final MethodHandle guard = noGuard ? null : NashornGuards.getMapGuard(getMap()); + final ScriptObject owner = find.getOwner(); if (methodHandle != null) { assert methodHandle.type().returnType().equals(returnType); @@ -1798,18 +1776,18 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return new GuardedInvocation(methodHandle, guard); } - if (!property.hasGetterFunction(find.getOwner())) { + if (!property.hasGetterFunction(owner)) { // If not a scope bind to actual prototype as changing prototype will change the property map. // For scopes we install a filter that replaces the self object with the prototype owning the property. methodHandle = isScope() ? addProtoFilter(methodHandle, find.getProtoChainLength()) : - bindTo(methodHandle, find.getOwner()); + bindTo(methodHandle, owner); } - return new GuardedInvocation(methodHandle, noGuard ? null : getMap().getProtoGetSwitchPoint(proto, name), guard); + return new GuardedInvocation(methodHandle, noGuard ? null : getProtoSwitchPoint(name, owner), guard); } assert !NashornCallSiteDescriptor.isFastScope(desc); - return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard); + return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard); } private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) { @@ -1865,6 +1843,28 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return ScriptObject.class.isAssignableFrom(type.parameterType(0)) ? null : NashornGuards.getScriptObjectGuard(); } + /** + * Get a switch point for a property with the given {@code name} that will be invalidated when + * the property definition is changed in this object's prototype chain. Returns {@code null} if + * the property is defined in this object itself. + * + * @param name the property name + * @param owner the property owner, null if property is not defined + * @return a SwitchPoint or null + */ + public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) { + if (owner == this || getProto() == null) { + return null; + } + + for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) { + ScriptObject parent = obj.getProto(); + parent.getMap().addListener(name, obj.getMap()); + } + + return getMap().getSwitchPoint(name); + } + /** * Find the appropriate SET method for an invoke dynamic call. * @@ -1921,8 +1921,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this))); } assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc); - final PropertyMap myMap = getMap(); - return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap)); + return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap())); } @SuppressWarnings("unused") @@ -2082,7 +2081,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr methodHandle = bindTo(methodHandle, UNDEFINED); } return new GuardedInvocation(methodHandle, - find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null, + getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()), getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func)); } } @@ -2134,7 +2133,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) { - return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap())); + return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), + getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap())); } private abstract static class ScriptObjectIterator implements Iterator { @@ -2215,12 +2215,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr if (fieldCount < fieldMaximum) { property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount); - notifyPropertyAdded(this, property); property = addOwnProperty(property); } else { int i = getMap().getSpillLength(); property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i); - notifyPropertyAdded(this, property); property = addOwnProperty(property); i = property.getSlot(); @@ -3274,7 +3272,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } final Property prop = find.getProperty(); - notifyPropertyDeleted(this, prop); deleteOwnProperty(prop); return true; diff --git a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java index 7390aadd0cd..bdbc8ec8b9a 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java @@ -80,7 +80,7 @@ final class SetMethodCreator { } /** - * This class encapsulates the results of looking up a setter method; it's basically a triple of a method hanle, + * This class encapsulates the results of looking up a setter method; it's basically a triple of a method handle, * a Property object, and flags for invocation. * */ @@ -170,7 +170,10 @@ final class SetMethodCreator { private SetMethod createNewPropertySetter() { final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter(); - sobj.notifyPropertyAdded(sobj, sm.property); + final PropertyListeners listeners = map.getListeners(); + if (listeners != null) { + listeners.propertyAdded(sm.property); + } return sm; } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java index 6e03dc60857..d4a28cd7fb4 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java @@ -36,6 +36,7 @@ import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; +import jdk.nashorn.internal.runtime.linker.NashornGuards; /** * This class supports the handling of scope in a with body. @@ -123,7 +124,7 @@ public final class WithObject extends ScriptObject implements Scope { } if (find != null) { - return fixScopeCallSite(scope.lookup(desc, request), name); + return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner()); } // the property is not found - now check for @@ -175,7 +176,7 @@ public final class WithObject extends ScriptObject implements Scope { link = scope.lookup(desc, request); if (link != null) { - return fixScopeCallSite(link, name); + return fixScopeCallSite(link, name, null); } return null; @@ -252,13 +253,10 @@ public final class WithObject extends ScriptObject implements Scope { filterGuard(link, WITHEXPRESSIONFILTER)); } - private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) { + private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) { final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), - MH.guardWithTest( - expressionGuard(name), - filterGuard(newLink, WITHSCOPEFILTER), - MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class))); + NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER))); } private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) { @@ -288,9 +286,9 @@ public final class WithObject extends ScriptObject implements Scope { return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]); } - private MethodHandle expressionGuard(final String name) { + private MethodHandle expressionGuard(final String name, final ScriptObject owner) { final PropertyMap map = expression.getMap(); - final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name); + final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner); return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp); } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java index a8e79184d85..0b720be2740 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java @@ -37,10 +37,10 @@ import jdk.nashorn.internal.runtime.ScriptObject; * Constructor of method handles used to guard call sites. */ public final class NashornGuards { - private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); - private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); - private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); - private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class); + private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class); + private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class); + private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class); + private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class); // don't create me! private NashornGuards() { @@ -85,6 +85,17 @@ public final class NashornGuards { return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2); } + /** + * Combine two method handles of type {@code (Object)boolean} using logical AND. + * + * @param guard1 the first guard + * @param guard2 the second guard, only invoked if guard1 returns true + * @return true if both guard1 and guard2 returned true + */ + public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) { + return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class)); + } + @SuppressWarnings("unused") private static boolean isScriptObject(final Object self) { return self instanceof ScriptObject; diff --git a/nashorn/src/jdk/nashorn/internal/scripts/JO.java b/nashorn/src/jdk/nashorn/internal/scripts/JO.java index f2f000625d9..d6173918933 100644 --- a/nashorn/src/jdk/nashorn/internal/scripts/JO.java +++ b/nashorn/src/jdk/nashorn/internal/scripts/JO.java @@ -33,7 +33,7 @@ import jdk.nashorn.internal.runtime.ScriptObject; */ public class JO extends ScriptObject { - private static final PropertyMap map$ = PropertyMap.newMap().setIsShared(); + private static final PropertyMap map$ = PropertyMap.newMap(); /** * Returns the initial property map to be used. From 97dd276d1cfd0c2924695ae1fcfe5329fef2ae53 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Mon, 3 Mar 2014 09:21:42 -0800 Subject: [PATCH 238/265] 8036079: --with-boot-jdk-jvmargs configure options are ignored Reviewed-by: erikj --- common/autoconf/boot-jdk.m4 | 60 +++++++------ common/autoconf/configure.ac | 2 +- common/autoconf/generated-configure.sh | 114 ++++++++++++++----------- common/autoconf/spec.gmk.in | 2 +- 4 files changed, 97 insertions(+), 81 deletions(-) diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index dde3c926c2f..170049731dc 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -341,39 +341,45 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], [ ############################################################################## # - # Specify options for anything that is run with the Boot JDK. + # Specify jvm options for anything that is run with the Boot JDK. + # Not all JVM:s accept the same arguments on the command line. # AC_ARG_WITH(boot-jdk-jvmargs, [AS_HELP_STRING([--with-boot-jdk-jvmargs], - [specify JVM arguments to be passed to all invocations of the Boot JDK, overriding the default values, + [specify JVM arguments to be passed to all java invocations of boot JDK, overriding the default values, e.g --with-boot-jdk-jvmargs="-Xmx8G -enableassertions"])]) - if test "x$with_boot_jdk_jvmargs" = x; then - # Not all JVM:s accept the same arguments on the command line. - # OpenJDK specific increase in thread stack for JDK build, - # well more specifically, when running javac. - if test "x$BUILD_NUM_BITS" = x32; then - STACK_SIZE=768 - else - # Running Javac on a JVM on a 64-bit machine, the stack takes more space - # since 64-bit pointers are pushed on the stach. Apparently, we need - # to increase the stack space when javacing the JDK.... - STACK_SIZE=1536 - fi + AC_MSG_CHECKING([flags for boot jdk java command] ) - # Minimum amount of heap memory. - ADD_JVM_ARG_IF_OK([-Xms64M],boot_jdk_jvmargs,[$JAVA]) - if test "x$OPENJDK_TARGET_OS" = "xmacosx" || test "x$OPENJDK_TARGET_CPU" = "xppc64" ; then - # Why does macosx need more heap? Its the huge JDK batch. - ADD_JVM_ARG_IF_OK([-Xmx1600M],boot_jdk_jvmargs,[$JAVA]) - else - ADD_JVM_ARG_IF_OK([-Xmx1100M],boot_jdk_jvmargs,[$JAVA]) - fi - # When is adding -client something that speeds up the JVM? - # ADD_JVM_ARG_IF_OK([-client],boot_jdk_jvmargs,[$JAVA]) - ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs,[$JAVA]) - # Disable special log output when a debug build is used as Boot JDK... - ADD_JVM_ARG_IF_OK([-XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput],boot_jdk_jvmargs,[$JAVA]) + # Starting amount of heap memory. + ADD_JVM_ARG_IF_OK([-Xms64M],boot_jdk_jvmargs,[$JAVA]) + + # Maximum amount of heap memory. + # Maximum stack size. + if test "x$BUILD_NUM_BITS" = x32; then + JVM_MAX_HEAP=1100M + STACK_SIZE=768 + else + # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit + # pointers are used. Apparently, we need to increase the heap and stack + # space for the jvm. More specifically, when running javac to build huge + # jdk batch + JVM_MAX_HEAP=1600M + STACK_SIZE=1536 fi + ADD_JVM_ARG_IF_OK([-Xmx$JVM_MAX_HEAP],boot_jdk_jvmargs,[$JAVA]) + ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs,[$JAVA]) + + # Disable special log output when a debug build is used as Boot JDK... + ADD_JVM_ARG_IF_OK([-XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput],boot_jdk_jvmargs,[$JAVA]) + + # Apply user provided options. + ADD_JVM_ARG_IF_OK([$with_boot_jdk_jvmargs],boot_jdk_jvmargs,[$JAVA]) + + AC_MSG_RESULT([$boot_jdk_jvmargs]) + + # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs + JAVA_FLAGS=$boot_jdk_jvmargs AC_SUBST(BOOT_JDK_JVMARGS, $boot_jdk_jvmargs) + AC_SUBST(JAVA_FLAGS, $JAVA_FLAGS) ]) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index b9b374ca9c7..a96a1d2bf0b 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -31,7 +31,7 @@ AC_PREREQ([2.69]) -AC_INIT(OpenJDK, jdk8, build-dev@openjdk.java.net,,http://openjdk.java.net) +AC_INIT(OpenJDK, jdk9, build-dev@openjdk.java.net,,http://openjdk.java.net) AC_CONFIG_AUX_DIR([$TOPDIR/common/autoconf/build-aux]) m4_include([build-aux/pkg.m4]) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 3bf81ca7ce8..543fea05b55 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -6,7 +6,7 @@ # #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OpenJDK jdk8. +# Generated by GNU Autoconf 2.69 for OpenJDK jdk9. # # Report bugs to . # @@ -586,8 +586,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='OpenJDK' PACKAGE_TARNAME='openjdk' -PACKAGE_VERSION='jdk8' -PACKAGE_STRING='OpenJDK jdk8' +PACKAGE_VERSION='jdk9' +PACKAGE_STRING='OpenJDK jdk9' PACKAGE_BUGREPORT='build-dev@openjdk.java.net' PACKAGE_URL='http://openjdk.java.net' @@ -793,6 +793,7 @@ JAXWS_TOPDIR JAXP_TOPDIR CORBA_TOPDIR LANGTOOLS_TOPDIR +JAVA_FLAGS BOOT_JDK_JVMARGS JAVAC_FLAGS BOOT_JDK_SOURCETARGET @@ -1725,7 +1726,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OpenJDK jdk8 to adapt to many kinds of systems. +\`configure' configures OpenJDK jdk9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1795,7 +1796,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenJDK jdk8:";; + short | recursive ) echo "Configuration of OpenJDK jdk9:";; esac cat <<\_ACEOF @@ -1871,8 +1872,8 @@ Optional Packages: number is not set.[username_builddateb00] --with-build-number Set build number value for build [b00] --with-boot-jdk path to Boot JDK (used to bootstrap build) [probed] - --with-boot-jdk-jvmargs specify JVM arguments to be passed to all - invocations of the Boot JDK, overriding the default + --with-boot-jdk-jvmargs specify JVM arguments to be passed to all java + invocations of boot JDK, overriding the default values, e.g --with-boot-jdk-jvmargs="-Xmx8G -enableassertions" --with-add-source-root for each and every source directory, look in this @@ -2116,7 +2117,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenJDK configure jdk8 +OpenJDK configure jdk9 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2812,7 +2813,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OpenJDK $as_me jdk8, which was +It was created by OpenJDK $as_me jdk9, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4220,7 +4221,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1393490405 +DATE_WHEN_GENERATED=1393867368 ############################################################################### # @@ -25842,7 +25843,8 @@ $as_echo "$tool_specified" >&6; } ############################################################################## # - # Specify options for anything that is run with the Boot JDK. + # Specify jvm options for anything that is run with the Boot JDK. + # Not all JVM:s accept the same arguments on the command line. # # Check whether --with-boot-jdk-jvmargs was given. @@ -25851,20 +25853,10 @@ if test "${with_boot_jdk_jvmargs+set}" = set; then : fi - if test "x$with_boot_jdk_jvmargs" = x; then - # Not all JVM:s accept the same arguments on the command line. - # OpenJDK specific increase in thread stack for JDK build, - # well more specifically, when running javac. - if test "x$BUILD_NUM_BITS" = x32; then - STACK_SIZE=768 - else - # Running Javac on a JVM on a 64-bit machine, the stack takes more space - # since 64-bit pointers are pushed on the stach. Apparently, we need - # to increase the stack space when javacing the JDK.... - STACK_SIZE=1536 - fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command " >&5 +$as_echo_n "checking flags for boot jdk java command ... " >&6; } - # Minimum amount of heap memory. + # Starting amount of heap memory. $ECHO "Check if jvm arg is ok: -Xms64M" >&5 $ECHO "Command: $JAVA -Xms64M -version" >&5 @@ -25880,16 +25872,28 @@ fi JVM_ARG_OK=false fi - if test "x$OPENJDK_TARGET_OS" = "xmacosx" || test "x$OPENJDK_TARGET_CPU" = "xppc64" ; then - # Why does macosx need more heap? Its the huge JDK batch. - $ECHO "Check if jvm arg is ok: -Xmx1600M" >&5 - $ECHO "Command: $JAVA -Xmx1600M -version" >&5 - OUTPUT=`$JAVA -Xmx1600M -version 2>&1` + # Maximum amount of heap memory. + # Maximum stack size. + if test "x$BUILD_NUM_BITS" = x32; then + JVM_MAX_HEAP=1100M + STACK_SIZE=768 + else + # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit + # pointers are used. Apparently, we need to increase the heap and stack + # space for the jvm. More specifically, when running javac to build huge + # jdk batch + JVM_MAX_HEAP=1600M + STACK_SIZE=1536 + fi + + $ECHO "Check if jvm arg is ok: -Xmx$JVM_MAX_HEAP" >&5 + $ECHO "Command: $JAVA -Xmx$JVM_MAX_HEAP -version" >&5 + OUTPUT=`$JAVA -Xmx$JVM_MAX_HEAP -version 2>&1` FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs="$boot_jdk_jvmargs -Xmx1600M" + boot_jdk_jvmargs="$boot_jdk_jvmargs -Xmx$JVM_MAX_HEAP" JVM_ARG_OK=true else $ECHO "Arg failed:" >&5 @@ -25897,25 +25901,6 @@ fi JVM_ARG_OK=false fi - else - - $ECHO "Check if jvm arg is ok: -Xmx1100M" >&5 - $ECHO "Command: $JAVA -Xmx1100M -version" >&5 - OUTPUT=`$JAVA -Xmx1100M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs="$boot_jdk_jvmargs -Xmx1100M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - # When is adding -client something that speeds up the JVM? - # ADD_JVM_ARG_IF_OK([-client],boot_jdk_jvmargs,[$JAVA]) $ECHO "Check if jvm arg is ok: -XX:ThreadStackSize=$STACK_SIZE" >&5 $ECHO "Command: $JAVA -XX:ThreadStackSize=$STACK_SIZE -version" >&5 @@ -25931,7 +25916,8 @@ fi JVM_ARG_OK=false fi - # Disable special log output when a debug build is used as Boot JDK... + + # Disable special log output when a debug build is used as Boot JDK... $ECHO "Check if jvm arg is ok: -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" >&5 $ECHO "Command: $JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version" >&5 @@ -25947,10 +25933,34 @@ fi JVM_ARG_OK=false fi + + # Apply user provided options. + + $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5 + $ECHO "Command: $JAVA $with_boot_jdk_jvmargs -version" >&5 + OUTPUT=`$JAVA $with_boot_jdk_jvmargs -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs="$boot_jdk_jvmargs $with_boot_jdk_jvmargs" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs" >&5 +$as_echo "$boot_jdk_jvmargs" >&6; } + + # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs + JAVA_FLAGS=$boot_jdk_jvmargs + BOOT_JDK_JVMARGS=$boot_jdk_jvmargs + JAVA_FLAGS=$JAVA_FLAGS + ############################################################################### @@ -49138,7 +49148,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OpenJDK $as_me jdk8, which was +This file was extended by OpenJDK $as_me jdk9, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -49201,7 +49211,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -OpenJDK config.status jdk8 +OpenJDK config.status jdk9 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index d09fb0ea1c4..81dc5a99a81 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -441,7 +441,7 @@ OBJ_SUFFIX:=@OBJ_SUFFIX@ POST_STRIP_CMD:=@POST_STRIP_CMD@ POST_MCS_CMD:=@POST_MCS_CMD@ -JAVA_FLAGS:=@BOOT_JDK_JVMARGS@ +JAVA_FLAGS:=@JAVA_FLAGS@ JAVA=@FIXPATH@ @JAVA@ $(JAVA_FLAGS) From 6b9060ac8f5ad393506d0a2bfb4e09636a585da9 Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Mon, 3 Mar 2014 16:17:32 -0500 Subject: [PATCH 239/265] 8036142: Remove redundant call to annotateTypeLater with null Symbol AnnotateTypeLater (formerly typeAnnotate) with null as the symbol was a way to force attribution of type annotations, but this is now obsolete and problematic, and a silent noop condition Reviewed-by: jjg --- .../share/classes/com/sun/tools/javac/comp/Annotate.java | 2 +- .../src/share/classes/com/sun/tools/javac/comp/Attr.java | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index d7b5f4a11cc..cd1383b3b0a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -842,7 +842,7 @@ public class Annotate { final Env env, final Symbol sym, final DiagnosticPosition deferPos) { - + Assert.checkNonNull(sym); normal(new Annotate.Worker() { @Override public String toString() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 6090a579acb..1ab10af50e0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -769,13 +769,6 @@ public class Attr extends JCTree.Visitor { = deferredLintHandler.setPos(variable.pos()); try { - // Use null as symbol to not attach the type annotation to any symbol. - // The initializer will later also be visited and then we'll attach - // to the symbol. - // This prevents having multiple type annotations, just because of - // lazy constant value evaluation. - annotate.annotateTypeLater(variable.init, env, null, variable.pos()); - annotate.flush(); Type itype = attribExpr(variable.init, env, type); if (itype.constValue() != null) { return coerce(itype, type).constValue(); From 1f9569d235794474721433261061ebeef3da91e4 Mon Sep 17 00:00:00 2001 From: Neil Toda Date: Mon, 3 Mar 2014 15:03:17 -0800 Subject: [PATCH 240/265] 8035875: remove deprecated html tags from javadoc package-info.java file Reviewed-by: jjg --- .../classes/com/sun/javadoc/package-info.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/langtools/src/share/classes/com/sun/javadoc/package-info.java b/langtools/src/share/classes/com/sun/javadoc/package-info.java index 5fcc044d928..b8f711ff645 100644 --- a/langtools/src/share/classes/com/sun/javadoc/package-info.java +++ b/langtools/src/share/classes/com/sun/javadoc/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,32 +91,32 @@ classes:
 import com.sun.javadoc.*;
 
-public class ListParams extends Doclet {
+public class ListParams extends Doclet {
 
-    public static boolean start(RootDoc root) {
-        ClassDoc[] classes = root.classes();
+    public static boolean start(RootDoc root) {
+        ClassDoc[] classes = root.classes();
         for (int i = 0; i < classes.length; ++i) {
-            ClassDoc cd = classes[i];
-            printMembers(cd.constructors());
-            printMembers(cd.methods());
+            ClassDoc cd = classes[i];
+            printMembers(cd.constructors());
+            printMembers(cd.methods());
         }
         return true;
     }
 
-    static void printMembers(ExecutableMemberDoc[] mems) {
+    static void printMembers(ExecutableMemberDoc[] mems) {
         for (int i = 0; i < mems.length; ++i) {
-            ParamTag[] params = mems[i].paramTags();
-            System.out.println(mems[i].qualifiedName());
+            ParamTag[] params = mems[i].paramTags();
+            System.out.println(mems[i].qualifiedName());
             for (int j = 0; j < params.length; ++j) {
-                System.out.println("   " + params[j].parameterName()
-                    + " - " + params[j].parameterComment());
+                System.out.println("   " + params[j].parameterName()
+                    + " - " + params[j].parameterComment());
             }
         }
     }
 }
 
Interfaces and methods from the Javadoc API are marked in -red. +red. {@link com.sun.javadoc.Doclet Doclet} is an abstract class that specifies the invocation interface for doclets, {@link com.sun.javadoc.Doclet Doclet} holds class or interface information, From 72641e4e7fe0b6ec74ebd4fde14f65b57ee00939 Mon Sep 17 00:00:00 2001 From: Neil Toda Date: Mon, 3 Mar 2014 15:10:01 -0800 Subject: [PATCH 241/265] 8035877: javadoc classes are missing @return and @param tags Reviewed-by: jjg --- .../classes/com/sun/javadoc/ClassDoc.java | 58 +++++++++++------ .../share/classes/com/sun/javadoc/Doc.java | 18 +++++- .../share/classes/com/sun/javadoc/Doclet.java | 16 +++-- .../com/sun/javadoc/ExecutableMemberDoc.java | 37 ++++++----- .../classes/com/sun/javadoc/FieldDoc.java | 10 ++- .../classes/com/sun/javadoc/MemberDoc.java | 4 +- .../classes/com/sun/javadoc/MethodDoc.java | 12 ++-- .../classes/com/sun/javadoc/PackageDoc.java | 3 +- .../classes/com/sun/javadoc/Parameter.java | 8 ++- .../com/sun/javadoc/ProgramElementDoc.java | 22 ++++++- .../share/classes/com/sun/javadoc/SeeTag.java | 63 +++++++++++-------- .../com/sun/javadoc/SerialFieldTag.java | 11 +++- .../com/sun/javadoc/SourcePosition.java | 14 ++++- .../share/classes/com/sun/javadoc/Type.java | 54 ++++++++-------- .../classes/com/sun/javadoc/TypeVariable.java | 5 +- 15 files changed, 225 insertions(+), 110 deletions(-) diff --git a/langtools/src/share/classes/com/sun/javadoc/ClassDoc.java b/langtools/src/share/classes/com/sun/javadoc/ClassDoc.java index bf05b418ddd..092f79bf528 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ClassDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/ClassDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,28 +46,40 @@ public interface ClassDoc extends ProgramElementDoc, Type { /** * Return true if this class is abstract. Return true * for all interfaces. + * + * @return true if this class is abstract. Return true + * for all interfaces. */ boolean isAbstract(); /** * Return true if this class implements or interface extends - * java.io.Serializable. + * {@code java.io.Serializable}. * - * Since java.io.Externalizable extends - * java.io.Serializable, + * Since {@code java.io.Externalizable} extends + * {@code java.io.Serializable}, * Externalizable objects are also Serializable. + * + * @return true if this class implements or interface extends + * {@code java.io.Serializable}. */ boolean isSerializable(); /** * Return true if this class implements or interface extends - * java.io.Externalizable. + * {@code java.io.Externalizable}. + * + * @return true if this class implements or interface extends + * {@code java.io.Externalizable}. */ boolean isExternalizable(); /** * Return true if this class can be used as a target type of a lambda expression * or method reference. + * + * @return true if this class can be used as a target type of a lambda expression + * or method reference. */ boolean isFunctionalInterface(); @@ -84,14 +96,14 @@ public interface ClassDoc extends ProgramElementDoc, Type { * Return the Serializable fields of this class or interface. *

* Return either a list of default fields documented by - * serial tag
- * or return a single FieldDoc for - * serialPersistentField member. - * There should be a serialField tag for - * each Serializable field defined by an ObjectStreamField - * array component of serialPersistentField. + * {@code serial} tag
+ * or return a single {@code FieldDoc} for + * {@code serialPersistentField} member. + * There should be a {@code serialField} tag for + * each Serializable field defined by an {@code ObjectStreamField} + * array component of {@code serialPersistentField}. * - * @return an array of FieldDoc objects for the Serializable + * @return an array of {@code FieldDoc} objects for the Serializable * fields of this class or interface. * * @see #definesSerializableFields() @@ -101,7 +113,10 @@ public interface ClassDoc extends ProgramElementDoc, Type { /** * Return true if Serializable fields are explicitly defined with - * the special class member serialPersistentFields. + * the special class member {@code serialPersistentFields}. + * + * @return true if Serializable fields are explicitly defined with + * the special class member {@code serialPersistentFields}. * * @see #serializableFields() * @see SerialFieldTag @@ -113,7 +128,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * interface. * *

This method cannot accommodate certain generic type constructs. - * The superclassType method should be used instead. + * The {@code superclassType} method should be used instead. * * @return the ClassDoc for the superclass of this class, null if * there is no superclass. @@ -124,7 +139,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { /** * Return the superclass of this class. Return null if this is an * interface. A superclass is represented by either a - * ClassDoc or a ParametrizedType. + * {@code ClassDoc} or a {@code ParametrizedType}. * * @return the superclass of this class, or null if there is no superclass. * @since 1.5 @@ -134,7 +149,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { /** * Test whether this class is a subclass of the specified class. * If this is an interface, return false for all classes except - * java.lang.Object (we must keep this unexpected + * {@code java.lang.Object} (we must keep this unexpected * behavior for compatibility reasons). * * @param cd the candidate superclass. @@ -149,7 +164,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * Return an empty array if there are no interfaces. * *

This method cannot accommodate certain generic type constructs. - * The interfaceTypes method should be used instead. + * The {@code interfaceTypes} method should be used instead. * * @return an array of ClassDoc objects representing the interfaces. * @see #interfaceTypes @@ -163,7 +178,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * Return an empty array if there are no interfaces. * * @return an array of interfaces, each represented by a - * ClassDoc or a ParametrizedType. + * {@code ClassDoc} or a {@code ParametrizedType}. * @since 1.5 */ Type[] interfaceTypes(); @@ -225,7 +240,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * Return * included * methods in this class or interface. - * Same as methods(true). + * Same as {@code methods(true)}. * * @return an array of MethodDoc objects representing the included * methods in this class or interface. Does not include @@ -243,6 +258,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * modifier option. * Specify false to include all methods regardless of * access modifier option. + * * @return an array of MethodDoc objects representing the included * methods in this class or interface. */ @@ -281,7 +297,7 @@ public interface ClassDoc extends ProgramElementDoc, Type { * included * nested classes and interfaces within this class or interface. * This includes both static and non-static nested classes. - * (This method should have been named nestedClasses(), + * (This method should have been named {@code nestedClasses()}, * as inner classes are technically non-static.) Anonymous and local classes * or interfaces are not included. * @@ -312,6 +328,8 @@ public interface ClassDoc extends ProgramElementDoc, Type { * Search order: 1) qualified name, 2) nested in this class or interface, * 3) in this package, 4) in the class imports, 5) in the package imports. * Return the ClassDoc if found, null if not found. + * @param className Specify the class name to find as a String. + * @return the ClassDoc if found, null if not found. */ ClassDoc findClass(String className); diff --git a/langtools/src/share/classes/com/sun/javadoc/Doc.java b/langtools/src/share/classes/com/sun/javadoc/Doc.java index c258eeb647f..1ade63fe450 100644 --- a/langtools/src/share/classes/com/sun/javadoc/Doc.java +++ b/langtools/src/share/classes/com/sun/javadoc/Doc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,8 @@ public interface Doc extends Comparable { /** * Return the text of the comment for this doc item. * Tags have been removed. + * + * @return the text of the comment for this doc item. */ String commentText(); @@ -119,6 +121,8 @@ public interface Doc extends Comparable { * Return the full unprocessed text of the comment. Tags * are included as text. Used mainly for store and retrieve * operations like internalization. + * + * @return the full unprocessed text of the comment. */ String getRawCommentText(); @@ -126,6 +130,8 @@ public interface Doc extends Comparable { * Set the full unprocessed text of the comment. Tags * are included as text. Used mainly for store and retrieve * operations like internalization. + * + * @param rawDocumentation A String containing the full unprocessed text of the comment. */ void setRawCommentText(String rawDocumentation); @@ -143,7 +149,7 @@ public interface Doc extends Comparable { *

* This method satisfies the {@link java.lang.Comparable} interface. * - * @param obj the Object to be compared. + * @param obj the {@code Object} to be compared. * @return a negative integer, zero, or a positive integer as this Object * is less than, equal to, or greater than the given Object. * @exception ClassCastException the specified Object's type prevents it @@ -250,6 +256,10 @@ public interface Doc extends Comparable { * Return true if this Doc item is * included * in the result set. + * + * @return true if this Doc item is + * included + * in the result set. */ boolean isIncluded(); @@ -260,6 +270,10 @@ public interface Doc extends Comparable { * null because it has no location in the source file. * * @since 1.4 + * @return the source positino of the first line of the + * corresponding declaration, or null if + * no position is available. A default constructor returns + * null because it has no location in the source file. */ SourcePosition position(); } diff --git a/langtools/src/share/classes/com/sun/javadoc/Doclet.java b/langtools/src/share/classes/com/sun/javadoc/Doclet.java index 2a16980d6de..d7db96ebc08 100644 --- a/langtools/src/share/classes/com/sun/javadoc/Doclet.java +++ b/langtools/src/share/classes/com/sun/javadoc/Doclet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,15 @@ package com.sun.javadoc; * This is an example of a starting class for a doclet, * showing the entry-point methods. A starting class must * import com.sun.javadoc.* and implement the - * start(RootDoc) method, as described in the + * {@code start(RootDoc)} method, as described in the * package * description. If the doclet takes command line options, - * it must also implement optionLength and - * validOptions. + * it must also implement {@code optionLength} and + * {@code validOptions}. * *

A doclet supporting the language features added since 1.1 * (such as generics and annotations) should indicate this - * by implementing languageVersion. In the absence of + * by implementing {@code languageVersion}. In the absence of * this the doclet should not invoke any of the Doclet API methods * added since 1.5, and * the results of several other methods are modified so as @@ -45,7 +45,7 @@ package com.sun.javadoc; * the doclet. * *

To start the doclet, pass - * -doclet followed by the fully-qualified + * {@code -doclet} followed by the fully-qualified * name of the starting class on the javadoc tool command line. */ public abstract class Doclet { @@ -54,6 +54,7 @@ public abstract class Doclet { * Generate documentation here. * This method is required for all doclets. * + * @param root Supply the RootDoc to the method. * @return true on success. */ public static boolean start(RootDoc root) { @@ -69,6 +70,7 @@ public abstract class Doclet { * If this method is missing, Javadoc will print an invalid flag * error for every option. * + * @param option the option for which the number of arguements is returned. * @return number of arguments on the command line for an option * including the option name itself. Zero return means * option not known. Negative value means error occurred. @@ -88,6 +90,8 @@ public abstract class Doclet { * Printing option related error messages (using the provided * DocErrorReporter) is the responsibility of this method. * + * @param options Supply valid options as an array of Strings. + * @param reporter The DocErrorReporter responsible for these options. * @return true if the options are valid. */ public static boolean validOptions(String options[][], diff --git a/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java b/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java index 8792c9c537d..98c35cefe4a 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,11 +36,11 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Return exceptions this method or constructor throws. * If the type of the exception is a type variable, return the - * ClassDoc of its erasure. + * {@code ClassDoc} of its erasure. * - *

The thrownExceptions method cannot + *

The {@code thrownExceptions} method cannot * accommodate certain generic type constructs. The - * thrownExceptionTypes method should be used + * {@code thrownExceptionTypes} method should be used * instead. * * @return an array of ClassDoc[] representing the exceptions @@ -53,19 +53,23 @@ public interface ExecutableMemberDoc extends MemberDoc { * Return exceptions this method or constructor throws. * * @return an array representing the exceptions thrown by this method. - * Each array element is either a ClassDoc or a - * TypeVariable. + * Each array element is either a {@code ClassDoc} or a + * {@code TypeVariable}. * @since 1.5 */ Type[] thrownExceptionTypes(); /** * Return true if this method is native + * + * @return true if this method is native */ boolean isNative(); /** * Return true if this method is synchronized + * + * @return true if this method is synchronized */ boolean isSynchronized(); @@ -74,6 +78,7 @@ public interface ExecutableMemberDoc extends MemberDoc { * of arguments. * * @since 1.5 + * @return true if this method was declared to take a variable number of arguments. */ public boolean isVarArgs(); @@ -98,8 +103,8 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Return the throws tags in this method. * - * @return an array of ThrowTag containing all @exception - * and @throws tags. + * @return an array of ThrowTag containing all {@code @exception} + * and {@code @throws} tags. */ ThrowsTag[] throwsTags(); @@ -107,7 +112,7 @@ public interface ExecutableMemberDoc extends MemberDoc { * Return the param tags in this method, excluding the type * parameter tags. * - * @return an array of ParamTag containing all @param tags + * @return an array of ParamTag containing all {@code @param} tags * corresponding to the parameters of this method. */ ParamTag[] paramTags(); @@ -115,7 +120,7 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Return the type parameter tags in this method. * - * @return an array of ParamTag containing all @param tags + * @return an array of ParamTag containing all {@code @param} tags * corresponding to the type parameters of this method. * @since 1.5 */ @@ -123,8 +128,10 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Get the signature. It is the parameter list, type is qualified. - * For instance, for a method mymethod(String x, int y), - * it will return (java.lang.String,int). + * For instance, for a method {@code mymethod(String x, int y)}, + * it will return {@code (java.lang.String,int)}. + * + * @return the parameter list where type is qualified. */ String signature(); @@ -132,8 +139,10 @@ public interface ExecutableMemberDoc extends MemberDoc { * get flat signature. all types are not qualified. * return a String, which is the flat signiture of this member. * It is the parameter list, type is not qualified. - * For instance, for a method mymethod(String x, int y), - * it will return (String, int). + * For instance, for a method {@code mymethod(String x, int y)}, + * it will return {@code (String, int)}. + * + * @return a String, which is the flat signiture of this member. */ String flatSignature(); diff --git a/langtools/src/share/classes/com/sun/javadoc/FieldDoc.java b/langtools/src/share/classes/com/sun/javadoc/FieldDoc.java index 0565924b591..3039f24e959 100644 --- a/langtools/src/share/classes/com/sun/javadoc/FieldDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/FieldDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,16 +37,22 @@ public interface FieldDoc extends MemberDoc { /** * Get type of this field. + * + * @return the type of this field. */ Type type(); /** * Return true if this field is transient + * + * @return true if this field is transient */ boolean isTransient(); /** * Return true if this field is volatile + * + * @return true if this field is volatile */ boolean isVolatile(); @@ -54,7 +60,7 @@ public interface FieldDoc extends MemberDoc { * Return the serialField tags in this FieldDoc item. * * @return an array of SerialFieldTag objects containing - * all @serialField tags. + * all {@code @serialField} tags. */ SerialFieldTag[] serialFieldTags(); diff --git a/langtools/src/share/classes/com/sun/javadoc/MemberDoc.java b/langtools/src/share/classes/com/sun/javadoc/MemberDoc.java index ba21685d9dc..2eadeedafa0 100644 --- a/langtools/src/share/classes/com/sun/javadoc/MemberDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/MemberDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,8 @@ public interface MemberDoc extends ProgramElementDoc { /** * Returns true if this member was synthesized by the compiler. + * + * @return true if this member was synthesized by the compiler. */ boolean isSynthetic(); } diff --git a/langtools/src/share/classes/com/sun/javadoc/MethodDoc.java b/langtools/src/share/classes/com/sun/javadoc/MethodDoc.java index 83bc03f1487..dd447fa25e1 100644 --- a/langtools/src/share/classes/com/sun/javadoc/MethodDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/MethodDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,15 @@ public interface MethodDoc extends ExecutableMemberDoc { /** * Return true if this method is abstract + * + * @return true if this method is abstract */ boolean isAbstract(); /** * Return true if this method is default + * + * @return true if this method is default */ boolean isDefault(); @@ -54,9 +58,9 @@ public interface MethodDoc extends ExecutableMemberDoc { /** * Return the class containing the method that this method overrides. * - *

The overriddenClass method cannot + *

The {@code overriddenClass} method cannot * accommodate certain generic type constructs. The - * overriddenType method should be used instead. + * {@code overriddenType} method should be used instead. * * @return a ClassDoc representing the superclass * defining a method that this method overrides, or null if @@ -66,7 +70,7 @@ public interface MethodDoc extends ExecutableMemberDoc { /** * Return the type containing the method that this method overrides. - * It may be a ClassDoc or a ParameterizedType. + * It may be a {@code ClassDoc} or a {@code ParameterizedType}. * * @return the supertype whose method is overridden, or null if this * method does not override another in a superclass diff --git a/langtools/src/share/classes/com/sun/javadoc/PackageDoc.java b/langtools/src/share/classes/com/sun/javadoc/PackageDoc.java index 9a62ff424a7..5d870551f70 100644 --- a/langtools/src/share/classes/com/sun/javadoc/PackageDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/PackageDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,7 @@ public interface PackageDoc extends Doc { /** * Lookup a class or interface within this package. * + * @param className A String containing the name of the class to look up. * @return ClassDoc of found class or interface, * or null if not found. */ diff --git a/langtools/src/share/classes/com/sun/javadoc/Parameter.java b/langtools/src/share/classes/com/sun/javadoc/Parameter.java index a86b12e870c..f6d6a5dc9ed 100644 --- a/langtools/src/share/classes/com/sun/javadoc/Parameter.java +++ b/langtools/src/share/classes/com/sun/javadoc/Parameter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,12 +35,16 @@ public interface Parameter { /** * Get the type of this parameter. + * + * @return the type of this parameter. */ Type type(); /** * Get local name of this parameter. * For example if parameter is the short 'index', returns "index". + * + * @return the name of this parameter as a string. */ String name(); @@ -51,6 +55,8 @@ public interface Parameter { * This method returns a complete string * representation of the type, including the dimensions of arrays and * the type arguments of parameterized types. Names are qualified. + * + * @return a complete string representation of the type. */ String typeName(); diff --git a/langtools/src/share/classes/com/sun/javadoc/ProgramElementDoc.java b/langtools/src/share/classes/com/sun/javadoc/ProgramElementDoc.java index 4aac88b8eb6..d7b195e45d1 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ProgramElementDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/ProgramElementDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,10 +57,10 @@ public interface ProgramElementDoc extends Doc { /** * Get the fully qualified name of this program element. - * For example, for the class java.util.Hashtable, + * For example, for the class {@code java.util.Hashtable}, * return "java.util.Hashtable". *

- * For the method bar() in class Foo + * For the method {@code bar()} in class {@code Foo} * in the unnamed package, return "Foo.bar". * * @return the qualified name of the program element as a String. @@ -71,6 +71,8 @@ public interface ProgramElementDoc extends Doc { * Get the modifier specifier integer. * * @see java.lang.reflect.Modifier + * + * @return Get the modifier specifier integer. */ int modifierSpecifier(); @@ -82,6 +84,8 @@ public interface ProgramElementDoc extends Doc { * * return "public abstract". * Annotations are not included. + * + * @return "public abstract". */ String modifiers(); @@ -96,30 +100,42 @@ public interface ProgramElementDoc extends Doc { /** * Return true if this program element is public. + * + * @return true if this program element is public. */ boolean isPublic(); /** * Return true if this program element is protected. + * + * @return true if this program element is protected. */ boolean isProtected(); /** * Return true if this program element is private. + * + * @return true if this program element is private. */ boolean isPrivate(); /** * Return true if this program element is package private. + * + * @return true if this program element is package private. */ boolean isPackagePrivate(); /** * Return true if this program element is static. + * + * @return true if this program element is static. */ boolean isStatic(); /** * Return true if this program element is final. + * + * @return true if this program element is final. */ boolean isFinal(); } diff --git a/langtools/src/share/classes/com/sun/javadoc/SeeTag.java b/langtools/src/share/classes/com/sun/javadoc/SeeTag.java index 84295395d40..d88c5ccb9f2 100644 --- a/langtools/src/share/classes/com/sun/javadoc/SeeTag.java +++ b/langtools/src/share/classes/com/sun/javadoc/SeeTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,11 +31,11 @@ package com.sun.javadoc; * plain text. (The plain text might be a reference * to something not online, such as a printed book, or be a hard-coded * HTML link.) The reference can either be inline with the comment, - * using {@link}, or a separate block comment, - * using @see. - * Method name() returns "@link" (no curly braces) or + * using {@code {@link}}, or a separate block comment, + * using {@code @see}. + * Method {@code name()} returns "@link" (no curly braces) or * "@see", depending on the tag. - * Method kind() returns "@see" for both tags. + * Method {@code kind()} returns "@see" for both tags. * * @author Kaiyang Liu (original) * @author Robert Field (rewrite) @@ -45,44 +45,51 @@ package com.sun.javadoc; public interface SeeTag extends Tag { /** - * Get the label of the @see tag. + * Get the label of the {@code @see} tag. * Return null if no label is present. * For example, for: *

- *   @see String#trim() the trim method + *   {@code @see String#trim() the trim method} *

* return "the trim method". + * + * @return "the trim method". */ String label(); /** - * Get the package doc when @see references only a package. + * Get the package doc when {@code @see} references only a package. * Return null if the package cannot be found, or if - * @see references any other element (class, + * {@code @see} references any other element (class, * interface, field, constructor, method) or non-element. * For example, for: *

- *   @see java.lang + *   {@code @see java.lang} *

- * return the PackageDoc for java.lang. + * return the {@code PackageDoc} for {@code java.lang}. + * + * @return the {@code PackageDoc} for {@code java.lang}. */ public PackageDoc referencedPackage(); /** - * Get the class or interface name of the @see reference. + * Get the class or interface name of the {@code @see} reference. * The name is fully qualified if the name specified in the - * original @see tag was fully qualified, or if the class + * original {@code @see} tag was fully qualified, or if the class * or interface can be found; otherwise it is unqualified. - * If @see references only a package name, then return + * If {@code @see} references only a package name, then return * the package name instead. * For example, for: *

- *   @see String#valueOf(java.lang.Object) + *   {@code @see String#valueOf(java.lang.Object)} *

* return "java.lang.String". - * For "@see java.lang", return "java.lang". - * Return null if @see references a non-element, such as - * @see <a href="java.sun.com">. + * For "{@code @see java.lang}", return "java.lang". + * Return null if {@code @see} references a non-element, such as + * {@code @see <a href="java.sun.com">}. + * + * @return null if {@code @see} references a non-element, such as + * {@code @see <a href="java.sun.com">}. */ String referencedClassName(); @@ -91,36 +98,42 @@ public interface SeeTag extends Tag { * Return null if the class cannot be found. * For example, for: *

- *   @see String#valueOf(java.lang.Object) + *   {@code @see String#valueOf(java.lang.Object)} *

- * return the ClassDoc for java.lang.String. + * return the {@code ClassDoc} for {@code java.lang.String}. + * + * @return the {@code ClassDoc} for {@code java.lang.String}. */ ClassDoc referencedClass(); /** - * Get the field, constructor or method substring of the @see + * Get the field, constructor or method substring of the {@code @see} * reference. Return null if the reference is to any other * element or to any non-element. * References to member classes (nested classes) return null. * For example, for: *

- *   @see String#startsWith(String) + *   {@code @see String#startsWith(String)} *

* return "startsWith(String)". + * + * @return "startsWith(String)". */ String referencedMemberName(); /** * Get the member doc for the field, constructor or method - * referenced by @see. Return null if the member cannot + * referenced by {@code @see}. Return null if the member cannot * be found or if the reference is to any other element or to any * non-element. * References to member classes (nested classes) return null. * For example, for: *

- *   @see String#startsWith(java.lang.String) + *   {@code @see String#startsWith(java.lang.String)} *

- * return the MethodDoc for startsWith. + * return the {@code MethodDoc} for {@code startsWith}. + * + * @return the {@code MethodDoc} for {@code startsWith}. */ MemberDoc referencedMember(); } diff --git a/langtools/src/share/classes/com/sun/javadoc/SerialFieldTag.java b/langtools/src/share/classes/com/sun/javadoc/SerialFieldTag.java index 7f73936588f..ebf41145b0f 100644 --- a/langtools/src/share/classes/com/sun/javadoc/SerialFieldTag.java +++ b/langtools/src/share/classes/com/sun/javadoc/SerialFieldTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,11 +47,15 @@ public interface SerialFieldTag extends Tag, Comparable { /** * Return the serializable field name. + * + * @return the serializable field name. */ public String fieldName(); /** * Return the field type string. + * + * @return the field type string. */ public String fieldType(); @@ -66,6 +70,9 @@ public interface SerialFieldTag extends Tag, Comparable { /** * Return the field comment. If there is no serialField comment, return * javadoc comment of corresponding FieldDoc. + * + * @return the field comment. If there is no serialField comment, return + * javadoc comment of corresponding FieldDoc. */ public String description(); @@ -76,7 +83,7 @@ public interface SerialFieldTag extends Tag, Comparable { *

* Included to make SerialFieldTag items java.lang.Comparable. * - * @param obj the Object to be compared. + * @param obj the {@code Object} to be compared. * @return a negative integer, zero, or a positive integer as this Object * is less than, equal to, or greater than the given Object. * @exception ClassCastException the specified Object's type prevents it diff --git a/langtools/src/share/classes/com/sun/javadoc/SourcePosition.java b/langtools/src/share/classes/com/sun/javadoc/SourcePosition.java index dd94fcc0aa1..58a1ad6d566 100644 --- a/langtools/src/share/classes/com/sun/javadoc/SourcePosition.java +++ b/langtools/src/share/classes/com/sun/javadoc/SourcePosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,17 +36,25 @@ import java.io.File; */ public interface SourcePosition { /** The source file. Returns null if no file information is - * available. */ + * available. + * + * @return the source file as a File. + */ File file(); /** The line in the source file. The first line is numbered 1; - * 0 means no line number information is available. */ + * 0 means no line number information is available. + * + * @return the line number in the source file as an integer. + */ int line(); /** The column in the source file. The first column is * numbered 1; 0 means no column information is available. * Columns count characters in the input stream; a tab * advances the column number to the next 8-column tab stop. + * + * @return the column on the source line as an integer. */ int column(); diff --git a/langtools/src/share/classes/com/sun/javadoc/Type.java b/langtools/src/share/classes/com/sun/javadoc/Type.java index 77d9a732154..1700342ffee 100644 --- a/langtools/src/share/classes/com/sun/javadoc/Type.java +++ b/langtools/src/share/classes/com/sun/javadoc/Type.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,8 @@ package com.sun.javadoc; /** * Represents a type. A type can be a class or interface, an * invocation (like {@code List}) of a generic class or interface, - * a type variable, a wildcard type ("?"), - * or a primitive data type (like char). + * a type variable, a wildcard type ("{@code ?}"), + * or a primitive data type (like {@code char}). * * @since 1.2 * @author Kaiyang Liu (original) @@ -42,7 +42,8 @@ public interface Type { * Return unqualified name of type excluding any dimension information. *

* For example, a two dimensional array of String returns - * "String". + * "{@code String}". + * @return unqualified name of type excluding any dimension information. */ String typeName(); @@ -50,7 +51,8 @@ public interface Type { * Return qualified name of type excluding any dimension information. *

* For example, a two dimensional array of String - * returns "java.lang.String". + * returns "{@code java.lang.String}". + * @return qualified name of this type excluding any dimension information. */ String qualifiedTypeName(); @@ -60,9 +62,10 @@ public interface Type { * only the identifier of the innermost type is included. *

* For example, the class {@code Outer.Inner} returns - * "Inner". + * "{@code Inner}". * * @since 1.5 + * @return the simple name of this type excluding any dimension information. */ String simpleTypeName(); @@ -70,7 +73,8 @@ public interface Type { * Return the type's dimension information, as a string. *

* For example, a two dimensional array of String returns - * "[][]". + * "{@code [][]}". + * @return the type's dimension information as a string. */ String dimension(); @@ -79,7 +83,7 @@ public interface Type { * This includes any dimension information and type arguments. *

* For example, a two dimensional array of String may return - * "java.lang.String[][]", + * "{@code java.lang.String[][]}", * and the parameterized type {@code List} may return * "{@code java.util.List}". * @@ -96,66 +100,66 @@ public interface Type { boolean isPrimitive(); /** - * Return this type as a ClassDoc if it represents a class + * Return this type as a {@code ClassDoc} if it represents a class * or interface. Array dimensions are ignored. - * If this type is a ParameterizedType, - * TypeVariable, or WildcardType, return - * the ClassDoc of the type's erasure. If this is an - * AnnotationTypeDoc, return this as a ClassDoc + * If this type is a {@code ParameterizedType}, + * {@code TypeVariable}, or {@code WildcardType}, return + * the {@code ClassDoc} of the type's erasure. If this is an + * {@code AnnotationTypeDoc}, return this as a {@code ClassDoc} * (but see {@link #asAnnotationTypeDoc()}). * If this is a primitive type, return null. * - * @return the ClassDoc of this type, + * @return the {@code ClassDoc} of this type, * or null if it is a primitive type. */ ClassDoc asClassDoc(); /** - * Return this type as a ParameterizedType if it represents + * Return this type as a {@code ParameterizedType} if it represents * an invocation of a generic class or interface. Array dimensions * are ignored. * - * @return a ParameterizedType if the type is an + * @return a {@code ParameterizedType} if the type is an * invocation of a generic type, or null if it is not. * @since 1.5 */ ParameterizedType asParameterizedType(); /** - * Return this type as a TypeVariable if it represents + * Return this type as a {@code TypeVariable} if it represents * a type variable. Array dimensions are ignored. * - * @return a TypeVariable if the type is a type variable, + * @return a {@code TypeVariable} if the type is a type variable, * or null if it is not. * @since 1.5 */ TypeVariable asTypeVariable(); /** - * Return this type as a WildcardType if it represents + * Return this type as a {@code WildcardType} if it represents * a wildcard type. * - * @return a WildcardType if the type is a wildcard type, + * @return a {@code WildcardType} if the type is a wildcard type, * or null if it is not. * @since 1.5 */ WildcardType asWildcardType(); /** - * Returns this type as a AnnotatedType if it represents + * Returns this type as a {@code AnnotatedType} if it represents * an annotated type. * - * @return a AnnotatedType if the type if an annotated type, + * @return a {@code AnnotatedType} if the type if an annotated type, * or null if it is not * @since 1.8 */ AnnotatedType asAnnotatedType(); /** - * Return this type as an AnnotationTypeDoc if it represents + * Return this type as an {@code AnnotationTypeDoc} if it represents * an annotation type. Array dimensions are ignored. * - * @return an AnnotationTypeDoc if the type is an annotation + * @return an {@code AnnotationTypeDoc} if the type is an annotation * type, or null if it is not. * @since 1.5 */ @@ -165,7 +169,7 @@ public interface Type { * If this type is an array type, return the element type of the * array. Otherwise, return null. * - * @return a Type representing the element type or null. + * @return a {@code Type} representing the element type or null. * @since 1.8 */ Type getElementType(); diff --git a/langtools/src/share/classes/com/sun/javadoc/TypeVariable.java b/langtools/src/share/classes/com/sun/javadoc/TypeVariable.java index 4212f20a8e7..90f57d456c4 100644 --- a/langtools/src/share/classes/com/sun/javadoc/TypeVariable.java +++ b/langtools/src/share/classes/com/sun/javadoc/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,9 @@ public interface TypeVariable extends Type { /** * Get the annotations of this program element. * Return an empty array if there are none. + * + * @return the annotations of this program element or + * an empty array if there are none. */ public AnnotationDesc[] annotations(); From 735e586b5f9c8ea29fffeef15c04f99e6bc86ccb Mon Sep 17 00:00:00 2001 From: Neil Toda Date: Mon, 3 Mar 2014 15:24:31 -0800 Subject: [PATCH 242/265] 8035878: javadoc tool documentation should be using {@code ..} specifier Reviewed-by: jjg --- .../com/sun/javadoc/AnnotationValue.java | 12 ++++---- .../com/sun/javadoc/ExecutableMemberDoc.java | 8 +++--- .../classes/com/sun/javadoc/ParamTag.java | 10 +++---- .../com/sun/javadoc/ParameterizedType.java | 6 ++-- .../classes/com/sun/javadoc/RootDoc.java | 4 +-- .../share/classes/com/sun/javadoc/SeeTag.java | 6 ++-- .../share/classes/com/sun/javadoc/Tag.java | 28 +++++++++---------- .../classes/com/sun/javadoc/ThrowsTag.java | 18 ++++++------ .../classes/com/sun/javadoc/package-info.java | 12 ++++---- 9 files changed, 52 insertions(+), 52 deletions(-) diff --git a/langtools/src/share/classes/com/sun/javadoc/AnnotationValue.java b/langtools/src/share/classes/com/sun/javadoc/AnnotationValue.java index 253245ac0b7..d741c90e5a0 100644 --- a/langtools/src/share/classes/com/sun/javadoc/AnnotationValue.java +++ b/langtools/src/share/classes/com/sun/javadoc/AnnotationValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,11 +38,11 @@ public interface AnnotationValue { * Returns the value. * The type of the returned object is one of the following: *

  • a wrapper class for a primitive type - *
  • String - *
  • Type (representing a class literal) - *
  • FieldDoc (representing an enum constant) - *
  • AnnotationDesc - *
  • AnnotationValue[] + *
  • {@code String} + *
  • {@code Type} (representing a class literal) + *
  • {@code FieldDoc} (representing an enum constant) + *
  • {@code AnnotationDesc} + *
  • {@code AnnotationValue[]} *
* * @return the value. diff --git a/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java b/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java index 98c35cefe4a..9104c08159b 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/ExecutableMemberDoc.java @@ -103,8 +103,8 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Return the throws tags in this method. * - * @return an array of ThrowTag containing all {@code @exception} - * and {@code @throws} tags. + * @return an array of ThrowTag containing all {@code @exception} + * and {@code @throws} tags. */ ThrowsTag[] throwsTags(); @@ -112,7 +112,7 @@ public interface ExecutableMemberDoc extends MemberDoc { * Return the param tags in this method, excluding the type * parameter tags. * - * @return an array of ParamTag containing all {@code @param} tags + * @return an array of ParamTag containing all {@code @param} tags * corresponding to the parameters of this method. */ ParamTag[] paramTags(); @@ -120,7 +120,7 @@ public interface ExecutableMemberDoc extends MemberDoc { /** * Return the type parameter tags in this method. * - * @return an array of ParamTag containing all {@code @param} tags + * @return an array of ParamTag containing all {@code @param} tags * corresponding to the type parameters of this method. * @since 1.5 */ diff --git a/langtools/src/share/classes/com/sun/javadoc/ParamTag.java b/langtools/src/share/classes/com/sun/javadoc/ParamTag.java index c39082ee6f6..40b34e6d514 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ParamTag.java +++ b/langtools/src/share/classes/com/sun/javadoc/ParamTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ public interface ParamTag extends Tag { /** * Return the name of the parameter or type parameter - * associated with this ParamTag. + * associated with this {@code ParamTag}. * The angle brackets delimiting a type parameter are not part of * its name. * @@ -48,18 +48,18 @@ public interface ParamTag extends Tag { /** * Return the parameter comment - * associated with this ParamTag. + * associated with this {@code ParamTag}. * * @return the parameter comment. */ String parameterComment(); /** - * Return true if this ParamTag corresponds to a type + * Return true if this {@code ParamTag} corresponds to a type * parameter. Return false if it corresponds to an ordinary parameter * of a method or constructor. * - * @return true if this ParamTag corresponds to a type + * @return true if this {@code ParamTag} corresponds to a type * parameter. * @since 1.5 */ diff --git a/langtools/src/share/classes/com/sun/javadoc/ParameterizedType.java b/langtools/src/share/classes/com/sun/javadoc/ParameterizedType.java index 0bdcd71d5da..3cef8d1bd5c 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ParameterizedType.java +++ b/langtools/src/share/classes/com/sun/javadoc/ParameterizedType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,10 +97,10 @@ public interface ParameterizedType extends Type { * Return null is this is a top-level type. * *

For example, the containing type of - * {@code AnInterface.Nested} is the ClassDoc + * {@code AnInterface.Nested} is the {@code ClassDoc} * representing {@code AnInterface}, and the containing type of * {@code Outer.Inner} is the - * ParameterizedType representing {@code Outer}. + * {@code ParameterizedType} representing {@code Outer}. * * @return the type that contains this type as a member. */ diff --git a/langtools/src/share/classes/com/sun/javadoc/RootDoc.java b/langtools/src/share/classes/com/sun/javadoc/RootDoc.java index 36eded49de8..8a86b5514cb 100644 --- a/langtools/src/share/classes/com/sun/javadoc/RootDoc.java +++ b/langtools/src/share/classes/com/sun/javadoc/RootDoc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ public interface RootDoc extends Doc, DocErrorReporter { * Return the packages * specified * on the command line. - * If -subpackages and -exclude options + * If {@code -subpackages} and {@code -exclude} options * are used, return all the non-excluded packages. * * @return packages specified on the command line. diff --git a/langtools/src/share/classes/com/sun/javadoc/SeeTag.java b/langtools/src/share/classes/com/sun/javadoc/SeeTag.java index d88c5ccb9f2..7bbdab50506 100644 --- a/langtools/src/share/classes/com/sun/javadoc/SeeTag.java +++ b/langtools/src/share/classes/com/sun/javadoc/SeeTag.java @@ -31,7 +31,7 @@ package com.sun.javadoc; * plain text. (The plain text might be a reference * to something not online, such as a printed book, or be a hard-coded * HTML link.) The reference can either be inline with the comment, - * using {@code {@link}}, or a separate block comment, + * using {@code {@link}}, or a separate block comment, * using {@code @see}. * Method {@code name()} returns "@link" (no curly braces) or * "@see", depending on the tag. @@ -86,10 +86,10 @@ public interface SeeTag extends Tag { * return "java.lang.String". * For "{@code @see java.lang}", return "java.lang". * Return null if {@code @see} references a non-element, such as - * {@code @see <a href="java.sun.com">}. + * {@code @see }. * * @return null if {@code @see} references a non-element, such as - * {@code @see <a href="java.sun.com">}. + * {@code @see }. */ String referencedClassName(); diff --git a/langtools/src/share/classes/com/sun/javadoc/Tag.java b/langtools/src/share/classes/com/sun/javadoc/Tag.java index 32088845ef8..992a13f3c58 100644 --- a/langtools/src/share/classes/com/sun/javadoc/Tag.java +++ b/langtools/src/share/classes/com/sun/javadoc/Tag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import java.util.Locale; * Given a tag (e.g. "@since 1.2"), holds tag name (e.g. "@since") * and tag text (e.g. "1.2"). Tags with structure or which require * special processing are handled by subclasses such as ParamTag - * (for @param), SeeTag (for @see and {@link}), and ThrowsTag + * (for @param), SeeTag (for @see and {@link}), and ThrowsTag * (for @throws). * * @author Robert Field @@ -50,10 +50,10 @@ public interface Tag { /** * Return the name of this tag. The name is the string * starting with "@" that is used in a doc comment, such as - * @return. For inline tags, such as - * {@link}, the curly brackets + * {@code @return}. For inline tags, such as + * {@code {@link}}, the curly brackets * are not part of the name, so in this example the name - * would be simply @link. + * would be simply {@code @link}. * * @return the name of this tag */ @@ -69,7 +69,7 @@ public interface Tag { /** * Return the kind of this tag. * For most tags, - * kind() == name(); + * {@code kind() == name()}; * the following table lists those cases where there is more * than one tag of a given kind: * @@ -101,27 +101,27 @@ public interface Tag { String toString(); /** - * For a documentation comment with embedded {@link} - * tags, return an array of Tag objects. The entire + * For a documentation comment with embedded {@code {@link}} + * tags, return an array of {@code Tag} objects. The entire * doc comment is broken down into strings separated by - * {@link} tags, where each successive element + * {@code {@link}} tags, where each successive element * of the array represents either a string or - * {@link} tag, in order, from start to end. - * Each string is represented by a Tag object of + * {@code {@link}} tag, in order, from start to end. + * Each string is represented by a {@code Tag} object of * name "Text", where {@link #text()} returns the string. Each - * {@link} tag is represented by a + * {@code {@link}} tag is represented by a * {@link SeeTag} of name "@link" and kind "@see". * For example, given the following comment * tag: *

- * This is a {@link Doc commentlabel} example. + * {@code This is a {@link Doc commentlabel} example.} *

* return an array of Tag objects: *

diff --git a/langtools/src/share/classes/com/sun/javadoc/ThrowsTag.java b/langtools/src/share/classes/com/sun/javadoc/ThrowsTag.java index 2fa9d259d2d..8872a589027 100644 --- a/langtools/src/share/classes/com/sun/javadoc/ThrowsTag.java +++ b/langtools/src/share/classes/com/sun/javadoc/ThrowsTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ public interface ThrowsTag extends Tag { /** * Return the name of the exception - * associated with this ThrowsTag. + * associated with this {@code ThrowsTag}. * * @return name of the exception. */ @@ -47,30 +47,30 @@ public interface ThrowsTag extends Tag { /** * Return the exception comment - * associated with this ThrowsTag. + * associated with this {@code ThrowsTag}. * * @return exception comment. */ String exceptionComment(); /** - * Return a ClassDoc that represents the exception. + * Return a {@code ClassDoc} that represents the exception. * If the type of the exception is a type variable, return the - * ClassDoc of its erasure. + * {@code ClassDoc} of its erasure. * *

This method cannot accommodate certain generic type - * constructs. The exceptionType method + * constructs. The {@code exceptionType} method * should be used instead. * - * @return ClassDoc that represents the exception. + * @return {@code ClassDoc} that represents the exception. * @see #exceptionType */ ClassDoc exception(); /** * Return the type of the exception - * associated with this ThrowsTag. - * This may be a ClassDoc or a TypeVariable. + * associated with this {@code ThrowsTag}. + * This may be a {@code ClassDoc} or a {@code TypeVariable}. * * @return the type of the exception. * @since 1.5 diff --git a/langtools/src/share/classes/com/sun/javadoc/package-info.java b/langtools/src/share/classes/com/sun/javadoc/package-info.java index b8f711ff645..100318f5fcb 100644 --- a/langtools/src/share/classes/com/sun/javadoc/package-info.java +++ b/langtools/src/share/classes/com/sun/javadoc/package-info.java @@ -53,8 +53,8 @@ information can be extracted. When calling javadoc, you pass in package names and source file names -- these are called the specified packages and classes. You also pass in Javadoc options; the access control Javadoc options -(-public, -protected, -package, -and -private) filter program elements, producing a +({@code -public}, {@code -protected}, {@code -package}, +and {@code -private}) filter program elements, producing a result set, called the included set, or "documented" set. (The unfiltered set is also available through {@link com.sun.javadoc.PackageDoc#allClasses(boolean) allClasses(false)}.) @@ -78,15 +78,15 @@ describes explicitly which meaning is being used. A qualified class or interface name is one that has its package -name prepended to it, such as java.lang.String. A non-qualified -name has no package name, such as String. +name prepended to it, such as {@code java.lang.String}. A non-qualified +name has no package name, such as {@code String}.

Example

The following is an example doclet that -displays information in the @param tags of the processed +displays information in the {@code @param} tags of the processed classes:
 import com.sun.javadoc.*;
@@ -124,7 +124,7 @@ the invocation interface for doclets,
 superinterface of {@link com.sun.javadoc.MethodDoc} and
 {@link com.sun.javadoc.ConstructorDoc},
 and {@link com.sun.javadoc.ParamTag} holds information
-from "@param" tags.
+from "{@code @param}" tags.
 

This doclet when invoked with a command line like:


From 15411a6579d6ca66112442c2b4eca8ff8402647e Mon Sep 17 00:00:00 2001
From: Chris Hegarty 
Date: Tue, 4 Mar 2014 13:27:55 +0000
Subject: [PATCH 243/265] 8036584: Review comments from 8035897

Reviewed-by: alanb
---
 jdk/src/aix/native/java/net/aix_close.c       |  4 +--
 .../native/java/net/PlainDatagramSocketImpl.c | 36 ++++++++++---------
 .../solaris/native/java/net/PlainSocketImpl.c |  7 ++--
 .../native/java/net/SocketInputStream.c       | 14 ++++----
 jdk/src/solaris/native/java/net/bsd_close.c   |  7 ++--
 jdk/src/solaris/native/java/net/linux_close.c |  4 +--
 jdk/src/solaris/native/java/net/net_util_md.h |  2 +-
 .../solaris/native/java/net/solaris_close.c   |  4 +--
 8 files changed, 37 insertions(+), 41 deletions(-)

diff --git a/jdk/src/aix/native/java/net/aix_close.c b/jdk/src/aix/native/java/net/aix_close.c
index 7f8b16affe2..148e05da0c8 100644
--- a/jdk/src/aix/native/java/net/aix_close.c
+++ b/jdk/src/aix/native/java/net/aix_close.c
@@ -63,8 +63,6 @@
 #include 
 #include 
 
-#include "jni.h"
-
 /*
  * Stack allocated by thread when doing blocking operation
  */
@@ -384,7 +382,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
  * Auto restarts with adjusted timeout if interrupted by
  * signal other than our wakeup signal.
  */
-int NET_Timeout(JNIEnv *unused, int s, long timeout) {
+int NET_Timeout(int s, long timeout) {
     long prevtime = 0, newtime;
     struct timeval t;
     fdEntry_t *fdEntry = getFdEntry(s);
diff --git a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
index 2d1faa09d8e..587ce7117b9 100644
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
@@ -501,8 +501,7 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
         return -1;
     }
     if (timeout) {
-        int ret = NET_Timeout(env, fd, timeout);
-        JNU_CHECK_EXCEPTION_RETURN(env, -1);
+        int ret = NET_Timeout(fd, timeout);
         if (ret == 0) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                             "Peek timed out");
@@ -510,6 +509,8 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
         } else if (ret == -1) {
             if (errno == EBADF) {
                  JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+            } else if (errno == ENOMEM) {
+                 JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
             } else {
                  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");
             }
@@ -595,22 +596,24 @@ Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this,
     packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
     packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID);
     if (timeout) {
-        int ret = NET_Timeout(env, fd, timeout);
-        JNU_CHECK_EXCEPTION_RETURN(env, -1);
+        int ret = NET_Timeout(fd, timeout);
         if (ret == 0) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                             "Receive timed out");
             return -1;
         } else if (ret == -1) {
+            if (errno == ENOMEM) {
+                JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
 #ifdef __linux__
-            if (errno == EBADF) {
+            } else if (errno == EBADF) {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
             } else {
                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
-            }
 #else
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+            } else {
+                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 #endif
+            }
             return -1;
         }
     }
@@ -804,23 +807,24 @@ Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this,
         retry = JNI_FALSE;
 
         if (timeout) {
-            int ret = NET_Timeout(env, fd, timeout);
+            int ret = NET_Timeout(fd, timeout);
             if (ret <= 0) {
-                if ((*env)->ExceptionCheck(env)) {
-                    // fall-through, to potentially free, then return
-                } else if (ret == 0) {
+                if (ret == 0) {
                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                                     "Receive timed out");
                 } else if (ret == -1) {
+                    if (errno == ENOMEM) {
+                        JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
 #ifdef __linux__
-                    if (errno == EBADF) {
+                    } else if (errno == EBADF) {
                          JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
-                     } else {
-                         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
-                     }
+                    } else {
+                        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
 #else
-                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+                    } else {
+                        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 #endif
+                    }
                 }
 
                 if (mallocedPacket) {
diff --git a/jdk/src/solaris/native/java/net/PlainSocketImpl.c b/jdk/src/solaris/native/java/net/PlainSocketImpl.c
index 0f842a834d8..4cdeba0fa2d 100644
--- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c
+++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c
@@ -670,11 +670,10 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
         /* passing a timeout of 0 to poll will return immediately,
            but in the case of ServerSocket 0 means infinite. */
         if (timeout <= 0) {
-            ret = NET_Timeout(env, fd, -1);
+            ret = NET_Timeout(fd, -1);
         } else {
-            ret = NET_Timeout(env, fd, timeout);
+            ret = NET_Timeout(fd, timeout);
         }
-        JNU_CHECK_EXCEPTION(env);
         if (ret == 0) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                             "Accept timed out");
@@ -682,6 +681,8 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
         } else if (ret == -1) {
             if (errno == EBADF) {
                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+            } else if (errno == ENOMEM) {
+               JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
             } else {
                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
             }
diff --git a/jdk/src/solaris/native/java/net/SocketInputStream.c b/jdk/src/solaris/native/java/net/SocketInputStream.c
index f8412b325c2..9857d18573b 100644
--- a/jdk/src/solaris/native/java/net/SocketInputStream.c
+++ b/jdk/src/solaris/native/java/net/SocketInputStream.c
@@ -100,20 +100,20 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
     }
 
     if (timeout) {
-        nread = NET_Timeout(env, fd, timeout);
+        nread = NET_Timeout(fd, timeout);
         if (nread <= 0) {
-            if ((*env)->ExceptionCheck(env)) {
-                // fall-through, to potentially free, then return
-            } else if (nread == 0) {
+            if (nread == 0) {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
                             "Read timed out");
             } else if (nread == -1) {
                 if (errno == EBADF) {
                      JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
-                 } else {
-                     NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                } else if (errno == ENOMEM) {
+                    JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
+                } else {
+                    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                                   "select/poll failed");
-                 }
+                }
             }
             if (bufP != BUF) {
                 free(bufP);
diff --git a/jdk/src/solaris/native/java/net/bsd_close.c b/jdk/src/solaris/native/java/net/bsd_close.c
index ff51a018b99..21478ce6e5f 100644
--- a/jdk/src/solaris/native/java/net/bsd_close.c
+++ b/jdk/src/solaris/native/java/net/bsd_close.c
@@ -38,8 +38,6 @@
 #include 
 #include 
 
-#include "jni_util.h"
-
 /*
  * Stack allocated by thread when doing blocking operation
  */
@@ -333,7 +331,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
  * Auto restarts with adjusted timeout if interrupted by
  * signal other than our wakeup signal.
  */
-int NET_Timeout(JNIEnv *env, int s, long timeout) {
+int NET_Timeout(int s, long timeout) {
     long prevtime = 0, newtime;
     struct timeval t, *tp = &t;
     fd_set fds;
@@ -376,8 +374,7 @@ int NET_Timeout(JNIEnv *env, int s, long timeout) {
         int length = (howmany(s+1, NFDBITS)) * sizeof(int);
         fdsp = (fd_set *) calloc(1, length);
         if (fdsp == NULL) {
-            JNU_ThrowOutOfMemoryError(env, "NET_Select native heap allocation failed");
-            return 0;
+            return -1;   // errno will be set to ENOMEM
         }
         allocated = 1;
     }
diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c
index 2c08c16831b..f2e186f731e 100644
--- a/jdk/src/solaris/native/java/net/linux_close.c
+++ b/jdk/src/solaris/native/java/net/linux_close.c
@@ -36,8 +36,6 @@
 #include 
 #include 
 
-#include "jni.h"
-
 /*
  * Stack allocated by thread when doing blocking operation
  */
@@ -314,7 +312,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
  * Auto restarts with adjusted timeout if interrupted by
  * signal other than our wakeup signal.
  */
-int NET_Timeout(JNIEnv *unused, int s, long timeout) {
+int NET_Timeout(int s, long timeout) {
     long prevtime = 0, newtime;
     struct timeval t;
     fdEntry_t *fdEntry = getFdEntry(s);
diff --git a/jdk/src/solaris/native/java/net/net_util_md.h b/jdk/src/solaris/native/java/net/net_util_md.h
index d1cc12b9e27..e7150da6018 100644
--- a/jdk/src/solaris/native/java/net/net_util_md.h
+++ b/jdk/src/solaris/native/java/net/net_util_md.h
@@ -34,7 +34,7 @@
 
 #include 
 
-int NET_Timeout(JNIEnv *env, int s, long timeout);
+int NET_Timeout(int s, long timeout);
 int NET_Read(int s, void* buf, size_t len);
 int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
                  struct sockaddr *from, socklen_t *fromlen);
diff --git a/jdk/src/solaris/native/java/net/solaris_close.c b/jdk/src/solaris/native/java/net/solaris_close.c
index d59c45f3b4e..0cf7b5c96fc 100644
--- a/jdk/src/solaris/native/java/net/solaris_close.c
+++ b/jdk/src/solaris/native/java/net/solaris_close.c
@@ -28,8 +28,6 @@
 #include 
 #include 
 
-#include "jni.h"
-
 /* Support for restartable system calls on Solaris. */
 
 #define RESTARTABLE_RETURN_INT(_cmd) do {             \
@@ -88,7 +86,7 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
     RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
 }
 
-int NET_Timeout(JNIEnv *unused, int s, long timeout) {
+int NET_Timeout(int s, long timeout) {
     int result;
     struct timeval t;
     long prevtime, newtime;

From 2e148fb065ccfa1b44c52b3d87b4d279535d069a Mon Sep 17 00:00:00 2001
From: Robert Field 
Date: Tue, 4 Mar 2014 15:33:30 -0800
Subject: [PATCH 244/265] 8035776: Consistent Lambda construction

Reviewed-by: ahgross, briangoetz, dlsmith
---
 .../AbstractValidatingLambdaMetafactory.java  |  22 +-
 .../invoke/TypeConvertingMethodAdapter.java   |   2 +-
 .../lang/invoke/lambda/LambdaReceiver.java    |  70 ++++++
 .../invoke/lambda/LambdaReceiverBridge.java   |  71 ++++++
 .../LambdaReceiver_A.java                     |  28 +++
 .../java/lang/invoke/lambda/LambdaReturn.java |  92 ++++++++
 .../invoke/lambda/MetafactoryArityTest.java   | 169 ++++++++++++++
 .../lambda/MetafactoryParameterCastTest.java  | 211 ++++++++++++++++++
 .../lambda/MetafactorySamReturnTest.java      | 167 ++++++++++++++
 9 files changed, 829 insertions(+), 3 deletions(-)
 create mode 100644 jdk/test/java/lang/invoke/lambda/LambdaReceiver.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/LambdaReceiverBridge.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/LambdaReceiver_anotherpkg/LambdaReceiver_A.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/LambdaReturn.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/MetafactoryArityTest.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java
 create mode 100644 jdk/test/java/lang/invoke/lambda/MetafactorySamReturnTest.java

diff --git a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
index 10c3ed14663..3f91060ccc8 100644
--- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
@@ -200,6 +200,13 @@ import static sun.invoke.util.Wrapper.isWrapperType;
                                   implIsInstanceMethod ? "instance" : "static", implInfo,
                                   instantiatedArity, samArity));
         }
+        for (MethodType bridgeMT : additionalBridges) {
+            if (bridgeMT.parameterCount() != samArity) {
+                throw new LambdaConversionException(
+                        String.format("Incorrect number of parameters for bridge signature %s; incompatible with %s",
+                                      bridgeMT, samMethodType));
+            }
+        }
 
         // If instance: first captured arg (receiver) must be subtype of class where impl method is defined
         final int capturedStart;
@@ -232,7 +239,7 @@ import static sun.invoke.util.Wrapper.isWrapperType;
                throw new LambdaConversionException(
                        String.format("Invalid receiver type %s; not a subtype of implementation receiver type %s",
                                      receiverClass, implReceiverClass));
-             }
+            }
         } else {
             // no receiver
             capturedStart = 0;
@@ -274,11 +281,18 @@ import static sun.invoke.util.Wrapper.isWrapperType;
                     String.format("Type mismatch for lambda return: %s is not convertible to %s",
                                   actualReturnType, expectedType));
         }
-        if (!isAdaptableToAsReturn(expectedType, samReturnType)) {
+        if (!isAdaptableToAsReturnStrict(expectedType, samReturnType)) {
             throw new LambdaConversionException(
                     String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
                                   expectedType, samReturnType));
         }
+        for (MethodType bridgeMT : additionalBridges) {
+            if (!isAdaptableToAsReturnStrict(expectedType, bridgeMT.returnType())) {
+                throw new LambdaConversionException(
+                        String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
+                                      expectedType, bridgeMT.returnType()));
+            }
+        }
      }
 
     /**
@@ -330,6 +344,10 @@ import static sun.invoke.util.Wrapper.isWrapperType;
         return toType.equals(void.class)
                || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
     }
+    private boolean isAdaptableToAsReturnStrict(Class fromType, Class toType) {
+        if (fromType.equals(void.class)) return toType.equals(void.class);
+        return isAdaptableTo(fromType, toType, true);
+    }
 
 
     /*********** Logging support -- for debugging only, uncomment as needed
diff --git a/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
index b23ba663128..6bfbf6b601a 100644
--- a/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
+++ b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
@@ -212,7 +212,7 @@ class TypeConvertingMethodAdapter extends MethodVisitor {
      * @param functional
      */
     void convertType(Class arg, Class target, Class functional) {
-        if (arg.equals(target)) {
+        if (arg.equals(target) && arg.equals(functional)) {
             return;
         }
         if (arg == Void.TYPE || target == Void.TYPE) {
diff --git a/jdk/test/java/lang/invoke/lambda/LambdaReceiver.java b/jdk/test/java/lang/invoke/lambda/LambdaReceiver.java
new file mode 100644
index 00000000000..8e24379456e
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/LambdaReceiver.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary Consistent Lambda construction
+ */
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+
+import LambdaReceiver_anotherpkg.LambdaReceiver_A;
+
+public class LambdaReceiver extends LambdaReceiver_A {
+
+    interface IA {
+        int m(LambdaReceiver_A x);
+    }
+
+    static MethodHandles.Lookup l;
+    static MethodHandle h;
+    private static MethodType mt(Class k) { return MethodType.methodType(k); }
+    private static MethodType mt(Class k, Class k2) { return MethodType.methodType(k, k2); }
+    private static void mf(List errs, MethodType mts, MethodType mtf, boolean shouldWork) {
+    }
+
+    public static void main(String[] args) throws Throwable {
+        l = MethodHandles.lookup();
+        h = l.findVirtual(LambdaReceiver_A.class, "f", mt(int.class));
+        MethodType X = mt(int.class, LambdaReceiver.class);
+        MethodType A = mt(int.class, LambdaReceiver_A.class);
+        MethodType mti = mt(IA.class);
+        CallSite cs = LambdaMetafactory.metafactory(l, "m", mti,A,h,X);
+        IA p = (IA)cs.dynamicInvoker().invoke();
+        LambdaReceiver_A lra = new LambdaReceiver_A();
+        try {
+            p.m(lra);
+        } catch (ClassCastException cce) {
+            return;
+        }
+        throw new AssertionError("CCE expected");
+    }
+}
diff --git a/jdk/test/java/lang/invoke/lambda/LambdaReceiverBridge.java b/jdk/test/java/lang/invoke/lambda/LambdaReceiverBridge.java
new file mode 100644
index 00000000000..b1f3b859c98
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/LambdaReceiverBridge.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary Consistent Lambda construction
+ */
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+
+import LambdaReceiver_anotherpkg.LambdaReceiver_A;
+
+public class LambdaReceiverBridge extends LambdaReceiver_A {
+
+    interface IA {
+        int m(LambdaReceiver_A x);
+    }
+
+    static MethodHandles.Lookup l;
+    static MethodHandle h;
+    private static MethodType mt(Class k) { return MethodType.methodType(k); }
+    private static MethodType mt(Class k, Class k2) { return MethodType.methodType(k, k2); }
+    private static void mf(List errs, MethodType mts, MethodType mtf, boolean shouldWork) {
+    }
+
+    public static void main(String[] args) throws Throwable {
+        l = MethodHandles.lookup();
+        h = l.findVirtual(LambdaReceiver_A.class, "f", mt(int.class));
+        MethodType X = mt(int.class, LambdaReceiverBridge.class);
+        MethodType A = mt(int.class, LambdaReceiver_A.class);
+        MethodType mti = mt(IA.class);
+        CallSite cs = LambdaMetafactory.altMetafactory(l, "m", mti,X,h,X,
+                                          LambdaMetafactory.FLAG_BRIDGES, 1, A);
+        IA p = (IA)cs.dynamicInvoker().invoke();
+        LambdaReceiver_A lra = new LambdaReceiver_A();
+        try {
+            p.m(lra);
+        } catch (ClassCastException cce) {
+            return;
+        }
+        throw new AssertionError("CCE expected");
+    }
+}
diff --git a/jdk/test/java/lang/invoke/lambda/LambdaReceiver_anotherpkg/LambdaReceiver_A.java b/jdk/test/java/lang/invoke/lambda/LambdaReceiver_anotherpkg/LambdaReceiver_A.java
new file mode 100644
index 00000000000..e4d1c98336b
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/LambdaReceiver_anotherpkg/LambdaReceiver_A.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package LambdaReceiver_anotherpkg;
+
+public class LambdaReceiver_A {
+  protected final int f() { return 2; }
+}
diff --git a/jdk/test/java/lang/invoke/lambda/LambdaReturn.java b/jdk/test/java/lang/invoke/lambda/LambdaReturn.java
new file mode 100644
index 00000000000..27a02f05838
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/LambdaReturn.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary Consistent Lambda construction
+ */
+
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LambdaReturn {
+
+    interface I {
+        void m();
+    }
+
+    static void hereV() {}
+    static String hereS() { return "hi"; }
+    static MethodHandles.Lookup l;
+    private static MethodType mt(Class k) { return MethodType.methodType(k); }
+    private static MethodType mt(Class k, Class k2) { return MethodType.methodType(k, k2); }
+    private static void amf(List errs, MethodHandle h, MethodType mts, MethodType mtf, MethodType mtb, boolean shouldWork) {
+        MethodType mti = mt(I.class);
+        try {
+            LambdaMetafactory.altMetafactory(l, "m", mti, mts,h,mtf,
+                                          LambdaMetafactory.FLAG_BRIDGES, 1, mtb);
+        } catch(LambdaConversionException e) {
+            if (shouldWork)  errs.add("Error: Should work h=" + h + " s=" + mts + " -- f=" + mtf + " / b=" + mtb + " got: " + e);
+            return;
+        }
+        if (!shouldWork)  errs.add("Error: Should fail h=" + h + " s=" + mts + " -- f=" + mtf + " / b=" + mtb);
+    }
+
+    public static void main(String[] args) throws Throwable {
+        l = MethodHandles.lookup();
+        MethodHandle hV = l.findStatic(LambdaReturn.class, "hereV", mt(void.class));
+        MethodHandle hS = l.findStatic(LambdaReturn.class, "hereS", mt(String.class));
+        List errs = new ArrayList<>();
+        MethodType V = mt(void.class);
+        MethodType S = mt(String.class);
+        MethodType O = mt(Object.class);
+        MethodType I = mt(int.class);
+        amf(errs, hS, S, S, O, true);
+        amf(errs, hS, S, S, V, false);
+        amf(errs, hS, S, S, I, false);
+        amf(errs, hS, O, S, S, true);
+        amf(errs, hS, V, S, S, false);
+        amf(errs, hS, I, S, S, false);
+        amf(errs, hS, O, O, S, false);
+        amf(errs, hS, S, O, O, false);
+        amf(errs, hV, V, V, O, false);
+        amf(errs, hV, V, V, I, false);
+        amf(errs, hV, V, V, S, false);
+        amf(errs, hV, O, V, V, false);
+        amf(errs, hV, I, V, V, false);
+        amf(errs, hV, S, V, V, false);
+
+        if (errs.size() > 0) {
+            for (String err : errs) {
+                System.err.println(err);
+            }
+            throw new AssertionError("Errors: " + errs.size());
+        }
+    }
+}
diff --git a/jdk/test/java/lang/invoke/lambda/MetafactoryArityTest.java b/jdk/test/java/lang/invoke/lambda/MetafactoryArityTest.java
new file mode 100644
index 00000000000..568abbacca1
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/MetafactoryArityTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary metafactory should fail if arities are mismatched
+ */
+import java.lang.invoke.*;
+import java.util.Arrays;
+import static java.lang.invoke.MethodType.methodType;
+
+public class MetafactoryArityTest {
+
+    public interface I {}
+    public static class C { public static String m(int arg) { return ""; } }
+
+    static final MethodHandles.Lookup lookup = MethodHandles.lookup();
+    static final Class[] capInt = { int.class };
+    static final MethodHandle C_m;
+    static {
+        try { C_m = lookup.findStatic(C.class, "m", methodType(String.class, int.class)); }
+        catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); }
+    }
+
+    public static void main(String... args) {
+        MethodType unary = methodType(String.class, int.class);
+        MethodType nullary = methodType(String.class);
+        MethodType binary = methodType(String.class, int.class, int.class);
+        MethodType unaryCS = methodType(CharSequence.class, int.class);
+        MethodType nullaryCS = methodType(CharSequence.class);
+        MethodType binaryCS = methodType(CharSequence.class, int.class, int.class);
+        MethodType unaryObj = methodType(Object.class, int.class);
+        MethodType nullaryObj = methodType(Object.class);
+        MethodType binaryObj = methodType(Object.class, int.class, int.class);
+
+        test(true, C_m, unary, unary);
+        test(false, C_m, unary, nullary);
+        test(false, C_m, nullary, unary);
+        test(false, C_m, unary, binary);
+        test(false, C_m, binary, unary);
+
+        testBridge(true, C_m, unary, unary, unaryCS);
+        testBridge(false, C_m, unary, unary, nullaryCS);
+        testBridge(false, C_m, unary, unary, binaryCS);
+
+        testBridge(true, C_m, unary, unary, unaryCS, unaryObj);
+        testBridge(false, C_m, unary, unary, unaryCS, nullaryObj);
+        testBridge(false, C_m, unary, unary, unaryCS, binaryObj);
+
+        testCapture(true, C_m, capInt, nullary, nullary);
+        testCapture(false, C_m, capInt, binary, binary);
+        testCapture(false, C_m, capInt, nullary, unary);
+        testCapture(false, C_m, capInt, nullary, binary);
+        testCapture(false, C_m, capInt, unary, nullary);
+        testCapture(false, C_m, capInt, unary, binary);
+
+        testCaptureBridge(true, C_m, capInt, nullary, nullary, nullaryCS);
+        testCaptureBridge(false, C_m, capInt, unary, unary, unaryCS);
+        testCaptureBridge(false, C_m, capInt, nullary, nullary, unaryCS);
+        testCaptureBridge(false, C_m, capInt, nullary, nullary, binaryCS);
+
+        testCaptureBridge(true, C_m, capInt, nullary, nullary, nullaryCS, nullaryObj);
+        testCaptureBridge(false, C_m, capInt, unary, unary, unaryCS, unaryObj);
+        testCaptureBridge(false, C_m, capInt, nullary, nullary, nullaryCS, unaryObj);
+        testCaptureBridge(false, C_m, capInt, nullary, nullary, nullaryCS, binaryObj);
+    }
+
+    static void test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) {
+        tryMetafactory(correct, mh, new Class[]{}, instMT, samMT);
+        tryAltMetafactory(correct, mh, new Class[]{}, instMT, samMT);
+    }
+
+    static void testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs) {
+        tryAltMetafactory(correct, mh, new Class[]{}, instMT, samMT, bridgeMTs);
+    }
+
+    static void testCapture(boolean correct, MethodHandle mh, Class[] captured, MethodType instMT, MethodType samMT) {
+        tryMetafactory(correct, mh, captured, instMT, samMT);
+        tryAltMetafactory(correct, mh, captured, instMT, samMT);
+    }
+
+    static void testCaptureBridge(boolean correct, MethodHandle mh, Class[] captured,
+                                  MethodType instMT, MethodType samMT, MethodType... bridgeMTs) {
+        tryAltMetafactory(correct, mh, captured, instMT, samMT, bridgeMTs);
+    }
+
+    static void tryMetafactory(boolean correct, MethodHandle mh, Class[] captured,
+                               MethodType instMT, MethodType samMT) {
+        try {
+            LambdaMetafactory.metafactory(lookup, "run", methodType(I.class, captured),
+                                          samMT, mh, instMT);
+            if (!correct) {
+                throw new AssertionError("Uncaught linkage error:" +
+                                         " impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT);
+            }
+        }
+        catch (LambdaConversionException e) {
+            if (correct) {
+                throw new AssertionError("Unexpected linkage error:" +
+                                         " e=" + e +
+                                         ", impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT);
+            }
+        }
+    }
+
+    static void tryAltMetafactory(boolean correct, MethodHandle mh, Class[] captured,
+                                  MethodType instMT, MethodType samMT, MethodType... bridgeMTs) {
+        boolean bridge = bridgeMTs.length > 0;
+        Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4];
+        args[0] = samMT;
+        args[1] = mh;
+        args[2] = instMT;
+        args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0;
+        if (bridge) {
+            args[4] = bridgeMTs.length;
+            for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i];
+        }
+        try {
+            LambdaMetafactory.altMetafactory(lookup, "run", methodType(I.class, captured), args);
+            if (!correct) {
+                throw new AssertionError("Uncaught linkage error:" +
+                                         " impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT +
+                                         ", bridges=" + Arrays.toString(bridgeMTs));
+            }
+        }
+        catch (LambdaConversionException e) {
+            if (correct) {
+                throw new AssertionError("Unexpected linkage error:" +
+                                         " e=" + e +
+                                         ", impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT +
+                                         ", bridges=" + Arrays.toString(bridgeMTs));
+            }
+        }
+    }
+
+}
diff --git a/jdk/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java b/jdk/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java
new file mode 100644
index 00000000000..70a65e57917
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary Ensure that invocation parameters are always cast to the instantiatedMethodType
+ */
+import java.lang.invoke.*;
+import java.util.Arrays;
+import static java.lang.invoke.MethodType.methodType;
+
+public class MetafactoryParameterCastTest {
+
+    static final MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+    public static class A {
+    }
+
+    public static class B extends A {
+        void instance0() {}
+        void instance1(B arg) {}
+        static void static1(B arg) {}
+        static void static2(B arg1, B arg2) {}
+    }
+
+    public static class C extends B {}
+    public static class NotC extends B {}
+
+    public interface ASink { void take(A arg); }
+    public interface BSink { void take(B arg); }
+
+    public static void main(String... args) throws Throwable {
+        new MetafactoryParameterCastTest().test();
+    }
+
+    void test() throws Throwable {
+        MethodType takeA = methodType(void.class, A.class);
+        MethodType takeB = methodType(void.class, B.class);
+        MethodType takeC = methodType(void.class, C.class);
+
+        Class[] noCapture = {};
+        Class[] captureB = { B.class };
+
+        MethodHandle[] oneBParam = { lookup.findVirtual(B.class, "instance0", methodType(void.class)),
+                                     lookup.findStatic(B.class, "static1", methodType(void.class, B.class)) };
+        MethodHandle[] twoBParams = { lookup.findVirtual(B.class, "instance1", methodType(void.class, B.class)),
+                                      lookup.findStatic(B.class, "static2", methodType(void.class, B.class, B.class)) };
+
+        for (MethodHandle mh : oneBParam) {
+            // sam
+            tryASink(invokeMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));
+            tryBSink(invokeMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));
+            tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));
+            tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));
+
+            // bridge
+            tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeC, takeA));
+            tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeC, takeB));
+        }
+
+        for (MethodHandle mh : twoBParams) {
+            // sam
+            tryCapASink(invokeMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));
+            tryCapBSink(invokeMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));
+            tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));
+            tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));
+
+            // bridge
+            tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeC, takeA));
+            tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeC, takeB));
+        }
+    }
+
+    void tryASink(CallSite cs) throws Throwable {
+        ASink sink = (ASink) cs.dynamicInvoker().invoke();
+        tryASink(sink);
+    }
+
+    void tryCapASink(CallSite cs) throws Throwable {
+        ASink sink = (ASink) cs.dynamicInvoker().invoke(new B());
+        tryASink(sink);
+    }
+
+    void tryBSink(CallSite cs) throws Throwable {
+        BSink sink = (BSink) cs.dynamicInvoker().invoke();
+        tryBSink(sink);
+    }
+
+    void tryCapBSink(CallSite cs) throws Throwable {
+        BSink sink = (BSink) cs.dynamicInvoker().invoke(new B());
+        tryBSink(sink);
+    }
+
+    void tryASink(ASink sink) {
+        try { sink.take(new C()); }
+        catch (ClassCastException e) {
+            throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());
+        }
+
+        try {
+            sink.take(new B());
+            throw new AssertionError("Missing cast from A to C: " + lastMFParams());
+        }
+        catch (ClassCastException e) { /* expected */ }
+
+        try {
+            sink.take(new NotC());
+            throw new AssertionError("Missing cast from A to C: " + lastMFParams());
+        }
+        catch (ClassCastException e) { /* expected */ }
+    }
+
+    void tryBSink(BSink sink) {
+        try { sink.take(new C()); }
+        catch (ClassCastException e) {
+            throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());
+        }
+
+        try {
+            sink.take(new B());
+            throw new AssertionError("Missing cast from B to C: " + lastMFParams());
+        }
+        catch (ClassCastException e) { /* expected */ }
+
+        try {
+            sink.take(new NotC());
+            throw new AssertionError("Missing cast from B to C: " + lastMFParams());
+        }
+        catch (ClassCastException e) { /* expected */ }
+    }
+
+    MethodHandle lastMH;
+    Class[] lastCaptured;
+    MethodType lastInstMT;
+    MethodType lastSamMT;
+    MethodType[] lastBridgeMTs;
+
+    String lastMFParams() {
+        return "mh=" + lastMH +
+               ", captured=" + Arrays.toString(lastCaptured) +
+               ", instMT=" + lastInstMT +
+               ", samMT=" + lastSamMT +
+               ", bridgeMTs=" + Arrays.toString(lastBridgeMTs);
+    }
+
+    CallSite invokeMetafactory(MethodHandle mh, Class sam, String methodName,
+                               Class[] captured, MethodType instMT, MethodType samMT) {
+        lastMH = mh;
+        lastCaptured = captured;
+        lastInstMT = instMT;
+        lastSamMT = samMT;
+        lastBridgeMTs = new MethodType[]{};
+        try {
+            return LambdaMetafactory.metafactory(lookup, methodName, methodType(sam, captured),
+                                                 samMT, mh, instMT);
+        }
+        catch (LambdaConversionException e) {
+            // unexpected linkage error
+            throw new RuntimeException(e);
+        }
+    }
+
+    CallSite invokeAltMetafactory(MethodHandle mh, Class sam, String methodName,
+                                  Class[] captured, MethodType instMT,
+                                  MethodType samMT, MethodType... bridgeMTs) {
+        lastMH = mh;
+        lastCaptured = captured;
+        lastInstMT = instMT;
+        lastSamMT = samMT;
+        lastBridgeMTs = bridgeMTs;
+        try {
+            boolean bridge = bridgeMTs.length > 0;
+            Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4];
+            args[0] = samMT;
+            args[1] = mh;
+            args[2] = instMT;
+            args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0;
+            if (bridge) {
+                args[4] = bridgeMTs.length;
+                for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i];
+            }
+            return LambdaMetafactory.altMetafactory(lookup, methodName, methodType(sam, captured), args);
+        }
+        catch (LambdaConversionException e) {
+            // unexpected linkage error
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/jdk/test/java/lang/invoke/lambda/MetafactorySamReturnTest.java b/jdk/test/java/lang/invoke/lambda/MetafactorySamReturnTest.java
new file mode 100644
index 00000000000..4caf2624df9
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/MetafactorySamReturnTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035776
+ * @summary metafactory should fail if impl return does not match sam/bridge returns
+ */
+import java.lang.invoke.*;
+import java.util.Arrays;
+import static java.lang.invoke.MethodType.methodType;
+
+public class MetafactorySamReturnTest {
+
+    static final MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+    public interface I {}
+
+    public static class C {
+        public static void m_void(String arg) {}
+        public static boolean m_boolean(String arg) { return true; }
+        public static char m_char(String arg) { return 'x'; }
+        public static byte m_byte(String arg) { return 12; }
+        public static short m_short(String arg) { return 12; }
+        public static int m_int(String arg) { return 12; }
+        public static long m_long(String arg) { return 12; }
+        public static float m_float(String arg) { return 12; }
+        public static double m_double(String arg) { return 12; }
+        public static String m_String(String arg) { return ""; }
+        public static Integer m_Integer(String arg) { return 23; }
+        public static Object m_Object(String arg) { return new Object(); }
+
+        public static MethodHandle getMH(Class c) {
+            try {
+                return lookup.findStatic(C.class, "m_" + c.getSimpleName(), methodType(c, String.class));
+            }
+            catch (NoSuchMethodException | IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public static void main(String... args) {
+        Class[] t = { void.class, boolean.class, char.class,
+                         byte.class, short.class, int.class, long.class, float.class, double.class,
+                         String.class, Integer.class, Object.class };
+
+        for (int i = 0; i < t.length; i++) {
+            MethodHandle mh = C.getMH(t[i]);
+            for (int j = 0; j < t.length; j++) {
+                // TEMPORARY EXCEPTIONS
+                if (t[j] == void.class) continue;
+                if (t[i].isPrimitive() && t[j] == Object.class) continue;
+                if (t[i] == char.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue;
+                if (t[i] == byte.class && (t[j] == short.class || t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue;
+                if (t[i] == short.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue;
+                if (t[i] == int.class && (t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue;
+                if (t[i] == long.class && (t[j] == float.class || t[j] == double.class)) continue;
+                if (t[i] == float.class && t[j] == double.class) continue;
+                if (t[i] == int.class && t[j] == Integer.class) continue;
+                if (t[i] == Integer.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue;
+                // END TEMPORARY EXCEPTIONS
+                boolean correct = (t[i].isPrimitive() || t[j].isPrimitive())
+                                  ? t[i] == t[j]
+                                  : t[j].isAssignableFrom(t[i]);
+                MethodType mti = methodType(t[i], String.class);
+                MethodType mtiCS = methodType(t[i], CharSequence.class);
+                MethodType mtj = methodType(t[j], String.class);
+                MethodType mtjObj = methodType(t[j], Object.class);
+                test(correct, mh, mti, mtj);
+                testBridge(correct, mh, mti, mti, mtjObj);
+                testBridge(correct, mh, mti, mti, mtiCS, mtjObj);
+            }
+        }
+    }
+
+    static void test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) {
+        tryMetafactory(correct, mh, new Class[]{}, instMT, samMT);
+        tryAltMetafactory(correct, mh, new Class[]{}, instMT, samMT);
+    }
+
+    static void testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs) {
+        tryAltMetafactory(correct, mh, new Class[]{}, instMT, samMT, bridgeMTs);
+    }
+
+    static void tryMetafactory(boolean correct, MethodHandle mh, Class[] captured,
+                               MethodType instMT, MethodType samMT) {
+        try {
+            LambdaMetafactory.metafactory(lookup, "run", methodType(I.class, captured),
+                                          samMT, mh, instMT);
+            if (!correct) {
+                throw new AssertionError("Uncaught linkage error:" +
+                                         " impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT);
+            }
+        }
+        catch (LambdaConversionException e) {
+            if (correct) {
+                throw new AssertionError("Unexpected linkage error:" +
+                                         " e=" + e +
+                                         ", impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT);
+            }
+        }
+    }
+
+    static void tryAltMetafactory(boolean correct, MethodHandle mh, Class[] captured,
+                                  MethodType instMT, MethodType samMT, MethodType... bridgeMTs) {
+        boolean bridge = bridgeMTs.length > 0;
+        Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4];
+        args[0] = samMT;
+        args[1] = mh;
+        args[2] = instMT;
+        args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0;
+        if (bridge) {
+            args[4] = bridgeMTs.length;
+            for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i];
+        }
+        try {
+            LambdaMetafactory.altMetafactory(lookup, "run", methodType(I.class, captured), args);
+            if (!correct) {
+                throw new AssertionError("Uncaught linkage error:" +
+                                         " impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT +
+                                         ", bridges=" + Arrays.toString(bridgeMTs));
+            }
+        }
+        catch (LambdaConversionException e) {
+            if (correct) {
+                throw new AssertionError("Unexpected linkage error:" +
+                                         " e=" + e +
+                                         ", impl=" + mh +
+                                         ", captured=" + Arrays.toString(captured) +
+                                         ", inst=" + instMT +
+                                         ", sam=" + samMT +
+                                         ", bridges=" + Arrays.toString(bridgeMTs));
+            }
+        }
+    }
+
+}

From 3889cebe94102b83fc1ba0fd22afbc433c0f9b94 Mon Sep 17 00:00:00 2001
From: Joe Darcy 
Date: Tue, 4 Mar 2014 18:28:56 -0800
Subject: [PATCH 245/265] 8036568: Serial incompatibility in
 java.util.TreeMap.NavigableSubMap

Reviewed-by: smarks
---
 jdk/src/share/classes/java/util/TreeMap.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/jdk/src/share/classes/java/util/TreeMap.java b/jdk/src/share/classes/java/util/TreeMap.java
index fa97543a654..fda3e2a8e42 100644
--- a/jdk/src/share/classes/java/util/TreeMap.java
+++ b/jdk/src/share/classes/java/util/TreeMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1335,6 +1335,7 @@ public class TreeMap
      */
     abstract static class NavigableSubMap extends AbstractMap
         implements NavigableMap, java.io.Serializable {
+        private static final long serialVersionUID = -2102997345730753016L;
         /**
          * The backing map.
          */

From 751adf9af189c42f957b0ea2121447597b672ac7 Mon Sep 17 00:00:00 2001
From: Joe Darcy 
Date: Tue, 4 Mar 2014 18:32:27 -0800
Subject: [PATCH 246/265] 8035452: Fix serial lint warnings in core libs

Reviewed-by: smarks
---
 jdk/src/share/classes/java/util/EnumSet.java                  | 4 +++-
 .../share/classes/sun/reflect/annotation/ExceptionProxy.java  | 3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/jdk/src/share/classes/java/util/EnumSet.java b/jdk/src/share/classes/java/util/EnumSet.java
index 6e9eaad9bdf..af409973fbb 100644
--- a/jdk/src/share/classes/java/util/EnumSet.java
+++ b/jdk/src/share/classes/java/util/EnumSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,8 @@ import sun.misc.SharedSecrets;
  * @see EnumMap
  * @serial exclude
  */
+@SuppressWarnings("serial") // No serialVersionUID due to usage of
+                            // serial proxy pattern
 public abstract class EnumSet> extends AbstractSet
     implements Cloneable, java.io.Serializable
 {
diff --git a/jdk/src/share/classes/sun/reflect/annotation/ExceptionProxy.java b/jdk/src/share/classes/sun/reflect/annotation/ExceptionProxy.java
index 0fa18065e90..8495bc9260a 100644
--- a/jdk/src/share/classes/sun/reflect/annotation/ExceptionProxy.java
+++ b/jdk/src/share/classes/sun/reflect/annotation/ExceptionProxy.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,5 +37,6 @@ package sun.reflect.annotation;
  * @since   1.5
  */
 public abstract class ExceptionProxy implements java.io.Serializable {
+    private static final long serialVersionUID = 7241930048386631401L;
     protected abstract RuntimeException generateException();
 }

From 521f9a2048917006c1efb2d0f57c1e13c494035c Mon Sep 17 00:00:00 2001
From: Xue-Lei Andrew Fan 
Date: Wed, 5 Mar 2014 07:24:34 +0000
Subject: [PATCH 247/265] 8032473: Restructure JSSE regression test hierarchy
 in jdk test

Reviewed-by: weijun
---
 jdk/test/TEST.groups                              |  11 +++++++----
 .../ssl/SSLSecurity/ComKeyManagerFactoryImpl.java |   0
 .../net/ssl/SSLSecurity/ComSSLContextImpl.java    |   0
 .../SSLSecurity/ComTrustManagerFactoryImpl.java   |   0
 .../SSLSecurity/JavaxKeyManagerFactoryImpl.java   |   0
 .../net/ssl/SSLSecurity/JavaxSSLContextImpl.java  |   0
 .../SSLSecurity/JavaxTrustManagerFactoryImpl.java |   0
 .../com/sun/net/ssl/SSLSecurity/ProviderTest.java |   0
 .../sun/net/ssl/SSLSecurity/TruncateArray.java    |   0
 .../ssl => }/javax/net/ssl/Fix5070632.java        |   0
 .../javax/net/ssl/FixingJavadocs/ComURLNulls.java |   0
 .../net/ssl/FixingJavadocs/ImplicitHandshake.java |   2 +-
 .../net/ssl/FixingJavadocs/JavaxURLNulls.java     |   0
 .../net/ssl/FixingJavadocs/KMTMGetNothing.java    |   0
 .../net/ssl/FixingJavadocs/SSLSessionNulls.java   |   2 +-
 .../net/ssl/FixingJavadocs/SSLSocketInherit.java  |   2 +-
 .../ssl => }/javax/net/ssl/GetInstance.java       |   0
 .../CriticalSubjectAltName.java                   |   0
 .../DelayDefaultContextLoading.java               |   0
 .../ssl}/HttpsURLConnection/GetResponseCode.java  |   2 +-
 .../net/ssl}/HttpsURLConnection/crisubn.jks       | Bin
 .../net/ssl}/HttpsURLConnection/trusted.jks       | Bin
 jdk/test/{sun/security => javax/net}/ssl/README   |   0
 .../net/ssl}/SSLEngine/AcceptLargeFragments.java  |   0
 .../net/ssl}/SSLEngine/ArgCheck.java              |   2 +-
 .../net/ssl}/SSLEngine/Arrays.java                |   2 +-
 .../net/ssl}/SSLEngine/Basics.java                |   2 +-
 .../net/ssl}/SSLEngine/CheckStatus.java           |   2 +-
 .../net/ssl}/SSLEngine/ConnectionTest.java        |   2 +-
 .../net/ssl}/SSLEngine/ExtendedKeyEngine.java     |   2 +-
 .../net/ssl}/SSLEngine/ExtendedKeySocket.java     |   2 +-
 .../net/ssl}/SSLEngine/LargeBufs.java             |   2 +-
 .../net/ssl}/SSLEngine/LargePacket.java           |   2 +-
 .../ssl}/SSLEngine/MyX509ExtendedKeyManager.java  |   0
 .../net/ssl}/SSLEngine/MyX509KeyManager.java      |   0
 .../net/ssl}/SSLEngine/NoAuthClientAuth.java      |   2 +-
 .../net/ssl}/SSLEngine/SSLEngineResultArgs.java   |   0
 .../net/ssl}/SSLEngine/SSLEngineService.java      |   2 +-
 .../net/ssl}/SSLEngine/TestAllSuites.java         |   2 +-
 .../net/ssl}/SSLEngineResult/Deserialize.java     |   0
 .../ssl/SSLParameters/UseCipherSuitesOrder.java   |   2 +-
 .../SSLServerSocket/DefaultSSLServSocketFac.java  |   0
 .../ssl/SSLSession}/CheckMyTrustedKeystore.java   |  14 ++++++++------
 .../HttpsURLConnectionLocalCertificateChain.java  |   2 +-
 .../net/ssl/SSLSession}/JSSERenegotiate.java      |   2 +-
 .../ssl/SSLSession}/KeyManagerTrustManager.java   |   0
 .../ssl/SSLSession}/SSLCtxAccessToSessCtx.java    |   2 +-
 .../ssl/SSLSession}/SessionCacheSizeTests.java    |   2 +-
 .../net/ssl/SSLSession}/SessionTimeOutTests.java  |   2 +-
 .../net/ssl/SSLSession}/testEnabledProtocols.java |   2 +-
 .../javax/net/ssl/ServerName/IllegalSNIName.java  |   0
 .../net/ssl/ServerName/SSLEngineExplorer.java     |   4 ++--
 .../ServerName/SSLEngineExplorerMatchedSNI.java   |   4 ++--
 .../ServerName/SSLEngineExplorerUnmatchedSNI.java |   4 ++--
 .../ssl/ServerName/SSLEngineExplorerWithCli.java  |   4 ++--
 .../ssl/ServerName/SSLEngineExplorerWithSrv.java  |   4 ++--
 .../ssl/ServerName/SSLSocketConsistentSNI.java    |   2 +-
 .../net/ssl/ServerName/SSLSocketExplorer.java     |   4 ++--
 .../ssl/ServerName/SSLSocketExplorerFailure.java  |   4 ++--
 .../ServerName/SSLSocketExplorerMatchedSNI.java   |   4 ++--
 .../ServerName/SSLSocketExplorerUnmatchedSNI.java |   4 ++--
 .../ServerName/SSLSocketExplorerWithCliSNI.java   |   4 ++--
 .../ServerName/SSLSocketExplorerWithSrvSNI.java   |   4 ++--
 .../ssl/ServerName/SSLSocketInconsistentSNI.java  |   2 +-
 .../net/ssl/ServerName/SSLSocketSNISensitive.java |   0
 .../ssl/TLSv11/EmptyCertificateAuthorities.java   |   2 +-
 .../net/ssl/TLSv11/ExportableBlockCipher.java     |   2 +-
 .../net/ssl/TLSv11/ExportableStreamCipher.java    |   2 +-
 .../javax/net/ssl/TLSv11/GenericBlockCipher.java  |   2 +-
 .../javax/net/ssl/TLSv11/GenericStreamCipher.java |   2 +-
 .../net/ssl/TLSv12/DisabledShortRSAKeys.java      |   0
 .../javax/net/ssl/TLSv12/ShortRSAKey512.java      |   0
 .../javax/net/ssl/TLSv12/ShortRSAKeyGCM.java      |   0
 .../{sun/security => javax/net}/ssl/etc/keystore  | Bin
 .../security => javax/net}/ssl/etc/truststore     | Bin
 .../net}/ssl/etc/unknown_keystore                 | Bin
 .../sanity/ciphersuites/CheckCipherSuites.java    |   0
 .../sanity/ciphersuites/CipherSuitesInOrder.java  |   0
 .../net}/ssl/sanity/ciphersuites/NoKerberos.java  |   0
 .../net}/ssl/sanity/interop/CipherTest.java       |   0
 .../ssl/sanity/interop/ClientJSSEServerJSSE.java  |   0
 .../net}/ssl/sanity/interop/JSSEClient.java       |   0
 .../net}/ssl/sanity/interop/JSSEServer.java       |   0
 .../pluggability/CheckSSLContextExport.java       |   0
 .../sanity/pluggability/CheckSockFacExport1.java  |   0
 .../sanity/pluggability/CheckSockFacExport2.java  |   0
 .../ssl/sanity/pluggability/CipherSuites.java     |   0
 .../ssl/sanity/pluggability/MySSLContextImpl.java |   0
 .../ssl/sanity/pluggability/MySSLEngineImpl.java  |   0
 .../pluggability/MySSLServerSocketFacImpl.java    |   0
 .../sanity/pluggability/MySSLSocketFacImpl.java   |   0
 .../net}/ssl/templates/SSLCapabilities.java       |   0
 .../net}/ssl/templates/SSLEngineTemplate.java     |   0
 .../net}/ssl/templates/SSLExplorer.java           |   0
 .../ssl/templates/SSLSocketSSLEngineTemplate.java |   2 +-
 .../net}/ssl/templates/SSLSocketTemplate.java     |   0
 .../www/protocol/https}/AbstractCallback.java     |   0
 .../www/protocol/https/ChunkedOutputStream.java}  |   9 +++++----
 .../www/protocol/https}/ClosedChannelList.java    |   0
 .../www/protocol/https}/HttpCallback.java         |   0
 .../www/protocol/https}/HttpTransaction.java      |   0
 .../protocol/https/HttpsClient/MyKeyManager.java  |   0
 .../protocol/https/HttpsClient/OriginServer.java  |   0
 .../protocol/https/HttpsClient/ProxyAuthTest.java |   2 +-
 .../https/HttpsClient/ProxyTunnelServer.java      |   0
 .../https/HttpsClient/ServerIdentityTest.java     |   0
 .../www/protocol/https/HttpsClient/dnsstore       | Bin
 .../www/protocol/https/HttpsClient/ipstore        | Bin
 .../https/HttpsURLConnection/B6216082.java        |   4 ++--
 .../https/HttpsURLConnection/B6226610.java        |   0
 .../https/HttpsURLConnection/CheckMethods.java    |   0
 .../HttpsURLConnection/CloseKeepAliveCached.java  |   2 +-
 .../HttpsURLConnection/CookieHandlerTest.java     |   2 +-
 .../HttpsURLConnection/CookieHttpsClientTest.java |   2 +-
 .../https/HttpsURLConnection/DNSIdentities.java   |   0
 .../HttpsURLConnection/HttpsCreateSockTest.java   |   2 +-
 .../https/HttpsURLConnection/HttpsPost.java       |   2 +-
 .../HttpsProxyStackOverflow.java                  |   0
 .../HttpsURLConnection/HttpsSocketFacTest.java    |   2 +-
 .../IPAddressDNSIdentities.java                   |   0
 .../HttpsURLConnection/IPAddressIPIdentities.java |   0
 .../https/HttpsURLConnection/IPIdentities.java    |   0
 .../https/HttpsURLConnection/Identities.java      |   0
 .../https/HttpsURLConnection/OriginServer.java    |   0
 .../https/HttpsURLConnection/PostThruProxy.java   |   2 +-
 .../https/HttpsURLConnection/PostThruProxy.sh     |   0
 .../HttpsURLConnection/PostThruProxyWithAuth.java |   2 +-
 .../HttpsURLConnection/PostThruProxyWithAuth.sh   |   0
 .../HttpsURLConnection/ProxyTunnelServer.java     |   0
 .../https/HttpsURLConnection/ReadTimeout.java     |   2 +-
 .../https/HttpsURLConnection/Redirect.java        |   2 +-
 .../https/HttpsURLConnection/RetryHttps.java      |   2 +-
 .../https/HttpsURLConnection/TunnelProxy.java     |   0
 .../https/NewImpl/ComHTTPSConnection.java         |   2 +-
 .../https/NewImpl/ComHostnameVerifier.java        |   0
 .../https/NewImpl/JavaxHTTPSConnection.java       |   2 +-
 .../https/NewImpl/JavaxHostnameVerifier.java      |   0
 .../www/protocol/https}/TestHttpsServer.java      |   0
 .../ssl => }/AppInputStream/ReadBlocksClose.java  |   2 +-
 .../ssl => }/AppInputStream/ReadHandshake.java    |   0
 .../ssl => }/AppInputStream/ReadZeroBytes.java    |   2 +-
 .../ssl => }/AppInputStream/RemoveMarkReset.java  |   2 +-
 .../AppOutputStream/NoExceptionOnClose.java       |   2 +-
 .../internal/ssl => }/CipherSuite/SSL_NULL.java   |   0
 .../ClientHandshaker/CipherSuiteOrder.java        |   2 +-
 .../ssl => }/ClientHandshaker/RSAExport.java      |   0
 .../ssl => }/DHKeyExchange/DHEKeySizing.java      |   0
 .../EngineArgs/DebugReportsOneExtraByte.java      |   2 +-
 .../EngineArgs/DebugReportsOneExtraByte.sh        |   0
 .../ssl => }/GenSSLConfigs/ClientThread.java      |   0
 .../internal/ssl => }/GenSSLConfigs/Handler.java  |   0
 .../ssl => }/GenSSLConfigs/ServerHandler.java     |   0
 .../ssl => }/GenSSLConfigs/ServerThread.java      |   0
 .../ssl => }/GenSSLConfigs/TestThread.java        |   0
 .../internal/ssl => }/GenSSLConfigs/Traffic.java  |   0
 .../ssl/internal/ssl => }/GenSSLConfigs/main.java |   4 ++--
 .../ssl => }/HandshakeOutStream/NullCerts.java    |   3 +--
 .../ssl => }/InputRecord/ClientHelloRead.java     |   2 +-
 .../ssl => }/InputRecord/OriginServer.java        |   0
 .../ssl => }/InputRecord/ProxyTunnelServer.java   |   0
 .../InputRecord/SSLSocketTimeoutNulls.java        |   2 +-
 .../ssl => }/ProtocolVersion/HttpsProtocols.java  |   2 +-
 .../ssl => }/SSLContextImpl/BadKSProvider.java    |   2 +-
 .../ssl => }/SSLContextImpl/BadTSProvider.java    |   2 +-
 .../CustomizedDefaultProtocols.java               |   0
 .../SSLContextImpl/DefaultEnabledProtocols.java   |   0
 .../ssl => }/SSLContextImpl/GoodProvider.java     |   2 +-
 .../SSLContextImpl/IllegalProtocolProperty.java   |   0
 .../ssl => }/SSLContextImpl/MD2InTrustAnchor.java |   0
 .../SSLContextImpl/NoOldVersionContext.java       |   0
 .../SSLContextImpl/NullGetAcceptedIssuers.java    |   0
 .../SSLContextImpl/SSLContextVersion.java         |   0
 .../ssl => }/SSLContextImpl/TrustTrustedCert.java |   0
 .../SSLEngineImpl/CloseEngineException.java       |   2 +-
 .../SSLEngineImpl/CloseInboundException.java      |   2 +-
 .../ssl => }/SSLEngineImpl/CloseStart.java        |   2 +-
 .../DelegatedTaskWrongException.java              |   2 +-
 .../SSLEngineImpl/EmptyExtensionData.java         |   2 +-
 .../SSLEngineImpl/EngineEnforceUseClientMode.java |   2 +-
 .../SSLEngineImpl/RehandshakeFinished.java        |   2 +-
 .../SSLEngineBadBufferArrayAccess.java            |   2 +-
 .../ssl => }/SSLEngineImpl/SSLEngineDeadlock.java |   2 +-
 .../ssl => }/SSLSessionContextImpl/Timeout.java   |   0
 .../ssl => }/SSLSessionImpl/HashCodeMissing.java  |   2 +-
 .../SSLSocketImpl/AsyncSSLSocketClose.java        |   2 +-
 .../ssl => }/SSLSocketImpl/CheckMethods.java      |   0
 .../SSLSocketImpl/ClientModeClientAuth.java       |   2 +-
 .../ssl => }/SSLSocketImpl/ClientTimeout.java     |   2 +-
 .../ssl => }/SSLSocketImpl/CloseSocket.java       |   0
 .../SSLSocketImpl/CloseSocketException.java       |   2 +-
 .../InvalidateServerSessionRenegotiate.java       |   2 +-
 .../ssl => }/SSLSocketImpl/LoopbackSSLSocket.java |   0
 .../ssl => }/SSLSocketImpl/NewSocketMethods.java  |   2 +-
 .../SSLSocketImpl/NoImpactServerRenego.java       |   2 +-
 .../ssl => }/SSLSocketImpl/NonAutoClose.java      |   3 +--
 .../SSLSocketImpl/NotifyHandshakeTest.java        |   2 +-
 .../SSLSocketImpl/NotifyHandshakeTest.policy      |   0
 .../ssl => }/SSLSocketImpl/NotifyHandshakeTest.sh |   0
 .../SSLSocketImpl/NotifyHandshakeTestHeyYou.java  |   0
 .../SSLSocketImpl/RejectClientRenego.java         |   2 +-
 .../ssl => }/SSLSocketImpl/ReuseAddr.java         |   2 +-
 .../ssl => }/SSLSocketImpl/ReverseNameLookup.java |   2 +-
 .../SSLSocketImplThrowsWrongExceptions.java       |   2 +-
 .../ssl => }/SSLSocketImpl/ServerTimeout.java     |   2 +-
 .../ssl => }/SSLSocketImpl/SetClientMode.java     |   2 +-
 .../UnconnectedSocketWrongExceptions.java         |   2 +-
 .../AnonCipherWithWantClientAuth.java             |   2 +-
 .../ssl => }/ServerHandshaker/GetPeerHost.java    |   2 +-
 .../ServerHandshaker/GetPeerHostClient.java       |   0
 .../ServerHandshaker/GetPeerHostServer.java       |   2 +-
 .../ssl => }/SocketCreation/SocketCreation.java   |   2 +-
 .../ssl => }/X509KeyManager/NullCases.java        |   0
 .../ssl => }/X509KeyManager/PreferredKey.java     |   2 +-
 .../X509KeyManager/SelectOneKeyOutOfMany.java     |   2 +-
 .../X509TrustManagerImpl/BasicConstraints.java    |   0
 .../X509TrustManagerImpl/CertRequestOverflow.java |   2 +-
 .../X509TrustManagerImpl/CheckNullEntity.java     |   2 +-
 .../X509TrustManagerImpl/ClientServer.java        |   2 +-
 .../X509TrustManagerImpl/ComodoHacker.java        |   0
 .../X509TrustManagerImpl/PKIXExtendedTM.java      |   0
 .../X509TrustManagerImpl/SelfIssuedCert.java      |   0
 .../X509TrustManagerImpl/SunX509ExtendedTM.java   |   0
 .../X509ExtendedTMEnabled.java                    |   2 +-
 .../ssl => }/rsa/BrokenRSAPrivateCrtKey.java      |   0
 .../ssl/internal/ssl => }/spi/ProviderInit.java   |   2 +-
 225 files changed, 141 insertions(+), 137 deletions(-)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/ComKeyManagerFactoryImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/ComSSLContextImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/ComTrustManagerFactoryImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/JavaxKeyManagerFactoryImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/JavaxSSLContextImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/JavaxTrustManagerFactoryImpl.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/ProviderTest.java (100%)
 rename jdk/test/{sun/security/ssl => }/com/sun/net/ssl/SSLSecurity/TruncateArray.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/Fix5070632.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/ComURLNulls.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/JavaxURLNulls.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/KMTMGetNothing.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/GetInstance.java (100%)
 rename jdk/test/{sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https => javax/net/ssl}/HttpsURLConnection/CriticalSubjectAltName.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/HttpsURLConnection/DelayDefaultContextLoading.java (100%)
 rename jdk/test/{sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https => javax/net/ssl}/HttpsURLConnection/GetResponseCode.java (99%)
 rename jdk/test/{sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https => javax/net/ssl}/HttpsURLConnection/crisubn.jks (100%)
 rename jdk/test/{sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https => javax/net/ssl}/HttpsURLConnection/trusted.jks (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/README (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/AcceptLargeFragments.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/ArgCheck.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/Arrays.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/Basics.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/CheckStatus.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/ConnectionTest.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/ExtendedKeyEngine.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/ExtendedKeySocket.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/LargeBufs.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/LargePacket.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/MyX509ExtendedKeyManager.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/MyX509KeyManager.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/NoAuthClientAuth.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/SSLEngineResultArgs.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/SSLEngineService.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngine/TestAllSuites.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl}/SSLEngineResult/Deserialize.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/SSLServerSocket/DefaultSSLServSocketFac.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/CheckMyTrustedKeystore.java (97%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/HttpsURLConnectionLocalCertificateChain.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/JSSERenegotiate.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/KeyManagerTrustManager.java (100%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/SSLCtxAccessToSessCtx.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/SessionCacheSizeTests.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/SessionTimeOutTests.java (99%)
 rename jdk/test/{sun/security/ssl/javax/net/ssl/NewAPIs => javax/net/ssl/SSLSession}/testEnabledProtocols.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/IllegalSNIName.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLEngineExplorer.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorer.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/ServerName/SSLSocketSNISensitive.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv11/ExportableBlockCipher.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv11/ExportableStreamCipher.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv11/GenericBlockCipher.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv11/GenericStreamCipher.java (99%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv12/ShortRSAKey512.java (100%)
 rename jdk/test/{sun/security/ssl => }/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/etc/keystore (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/etc/truststore (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/etc/unknown_keystore (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/ciphersuites/CheckCipherSuites.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/ciphersuites/CipherSuitesInOrder.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/ciphersuites/NoKerberos.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/interop/CipherTest.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/interop/ClientJSSEServerJSSE.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/interop/JSSEClient.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/interop/JSSEServer.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/CheckSSLContextExport.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/CheckSockFacExport1.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/CheckSockFacExport2.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/CipherSuites.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/MySSLContextImpl.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/MySSLEngineImpl.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/MySSLServerSocketFacImpl.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/sanity/pluggability/MySSLSocketFacImpl.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/templates/SSLCapabilities.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/templates/SSLEngineTemplate.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/templates/SSLExplorer.java (100%)
 rename jdk/test/{sun/security => javax/net}/ssl/templates/SSLSocketSSLEngineTemplate.java (99%)
 rename jdk/test/{sun/security => javax/net}/ssl/templates/SSLSocketTemplate.java (100%)
 rename jdk/test/sun/{security/ssl/sun/net/www/httpstest => net/www/protocol/https}/AbstractCallback.java (100%)
 rename jdk/test/sun/{security/ssl/sun/net/www/http/ChunkedOutputStream/Test.java => net/www/protocol/https/ChunkedOutputStream.java} (97%)
 rename jdk/test/sun/{security/ssl/sun/net/www/httpstest => net/www/protocol/https}/ClosedChannelList.java (100%)
 rename jdk/test/sun/{security/ssl/sun/net/www/httpstest => net/www/protocol/https}/HttpCallback.java (100%)
 rename jdk/test/sun/{security/ssl/sun/net/www/httpstest => net/www/protocol/https}/HttpTransaction.java (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/MyKeyManager.java (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/OriginServer.java (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/ProxyAuthTest.java (98%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/ProxyTunnelServer.java (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/ServerIdentityTest.java (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/dnsstore (100%)
 rename jdk/test/sun/{security/ssl/com/sun/net/ssl/internal => net}/www/protocol/https/HttpsClient/ipstore (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/B6216082.java (98%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/B6226610.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/CheckMethods.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/HttpsPost.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/IPIdentities.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/Identities.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/OriginServer.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/Redirect.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/RetryHttps.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/NewImpl/ComHTTPSConnection.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/NewImpl/ComHostnameVerifier.java (100%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java (99%)
 rename jdk/test/sun/{security/ssl/sun => }/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java (100%)
 rename jdk/test/sun/{security/ssl/sun/net/www/httpstest => net/www/protocol/https}/TestHttpsServer.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/AppInputStream/ReadBlocksClose.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/AppInputStream/ReadHandshake.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/AppInputStream/ReadZeroBytes.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/AppInputStream/RemoveMarkReset.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/AppOutputStream/NoExceptionOnClose.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/CipherSuite/SSL_NULL.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ClientHandshaker/CipherSuiteOrder.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ClientHandshaker/RSAExport.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/DHKeyExchange/DHEKeySizing.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/EngineArgs/DebugReportsOneExtraByte.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/EngineArgs/DebugReportsOneExtraByte.sh (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/ClientThread.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/Handler.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/ServerHandler.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/ServerThread.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/TestThread.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/Traffic.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/GenSSLConfigs/main.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/HandshakeOutStream/NullCerts.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/InputRecord/ClientHelloRead.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/InputRecord/OriginServer.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/InputRecord/ProxyTunnelServer.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/InputRecord/SSLSocketTimeoutNulls.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ProtocolVersion/HttpsProtocols.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/BadKSProvider.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/BadTSProvider.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/CustomizedDefaultProtocols.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/DefaultEnabledProtocols.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/GoodProvider.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/IllegalProtocolProperty.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/MD2InTrustAnchor.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/NoOldVersionContext.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/NullGetAcceptedIssuers.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/SSLContextVersion.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLContextImpl/TrustTrustedCert.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/CloseEngineException.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/CloseInboundException.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/CloseStart.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/DelegatedTaskWrongException.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/EmptyExtensionData.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/EngineEnforceUseClientMode.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/RehandshakeFinished.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLEngineImpl/SSLEngineDeadlock.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSessionContextImpl/Timeout.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSessionImpl/HashCodeMissing.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/AsyncSSLSocketClose.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/CheckMethods.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/ClientModeClientAuth.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/ClientTimeout.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/CloseSocket.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/CloseSocketException.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/InvalidateServerSessionRenegotiate.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/LoopbackSSLSocket.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NewSocketMethods.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NoImpactServerRenego.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NonAutoClose.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NotifyHandshakeTest.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NotifyHandshakeTest.policy (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NotifyHandshakeTest.sh (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/NotifyHandshakeTestHeyYou.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/RejectClientRenego.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/ReuseAddr.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/ReverseNameLookup.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/ServerTimeout.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/SetClientMode.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SSLSocketImpl/UnconnectedSocketWrongExceptions.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ServerHandshaker/AnonCipherWithWantClientAuth.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ServerHandshaker/GetPeerHost.java (96%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ServerHandshaker/GetPeerHostClient.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/ServerHandshaker/GetPeerHostServer.java (97%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/SocketCreation/SocketCreation.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509KeyManager/NullCases.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509KeyManager/PreferredKey.java (98%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509KeyManager/SelectOneKeyOutOfMany.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/BasicConstraints.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/CertRequestOverflow.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/CheckNullEntity.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/ClientServer.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/ComodoHacker.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/PKIXExtendedTM.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/SelfIssuedCert.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/SunX509ExtendedTM.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/X509TrustManagerImpl/X509ExtendedTMEnabled.java (99%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/rsa/BrokenRSAPrivateCrtKey.java (100%)
 rename jdk/test/sun/security/ssl/{com/sun/net/ssl/internal/ssl => }/spi/ProviderInit.java (99%)

diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index b624ca9b6eb..8e45f1998f7 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -101,7 +101,7 @@ jdk_nio = \
 
 jdk_net = \
     java/net \
-    com/sun/net \
+    com/sun/net/httpserver \
     com/oracle/net \
     sun/net
 
@@ -126,6 +126,9 @@ jdk_security3 = \
     com/sun/security \
     com/sun/org/apache/xml/internal/security \
     sun/security \
+    javax/net \
+    sun/net/www/protocol/https \
+    com/sun/net/ssl \
     lib/security
 
 jdk_security = \
@@ -489,7 +492,7 @@ needs_compact3 = \
   sun/security/provider/PolicyFile/Alias.java \
   sun/security/provider/PolicyFile/Comparator.java \
   sun/security/provider/PolicyFile/SelfWildcard.java \
-  sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java \
+  sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java \
   sun/security/util/Oid/OidFormat.java \
   sun/security/util/Resources/Format.java \
   sun/security/util/Resources/NewNamesFormat.java
@@ -587,8 +590,8 @@ needs_compact2 = \
   java/util/zip/ZipFile/DeleteTempJar.java \
   javax/crypto/Cipher/CipherStreamClose.java \
   sun/misc/URLClassPath/ClassnameCharTest.java \
-  sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \
-  sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java 
+  sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \
+  sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java 
 
 # Compact 1 adds full VM tests
 #
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComKeyManagerFactoryImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/ComKeyManagerFactoryImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComKeyManagerFactoryImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/ComKeyManagerFactoryImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComSSLContextImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/ComSSLContextImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComSSLContextImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/ComSSLContextImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComTrustManagerFactoryImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/ComTrustManagerFactoryImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ComTrustManagerFactoryImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/ComTrustManagerFactoryImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxKeyManagerFactoryImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/JavaxKeyManagerFactoryImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxKeyManagerFactoryImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/JavaxKeyManagerFactoryImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxSSLContextImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/JavaxSSLContextImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxSSLContextImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/JavaxSSLContextImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxTrustManagerFactoryImpl.java b/jdk/test/com/sun/net/ssl/SSLSecurity/JavaxTrustManagerFactoryImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/JavaxTrustManagerFactoryImpl.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/JavaxTrustManagerFactoryImpl.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ProviderTest.java b/jdk/test/com/sun/net/ssl/SSLSecurity/ProviderTest.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ProviderTest.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/ProviderTest.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/TruncateArray.java b/jdk/test/com/sun/net/ssl/SSLSecurity/TruncateArray.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/TruncateArray.java
rename to jdk/test/com/sun/net/ssl/SSLSecurity/TruncateArray.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/Fix5070632.java b/jdk/test/javax/net/ssl/Fix5070632.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/Fix5070632.java
rename to jdk/test/javax/net/ssl/Fix5070632.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/ComURLNulls.java b/jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/ComURLNulls.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/ComURLNulls.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java b/jdk/test/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java
index 8badfd66224..b1ef64ef88a 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java
+++ b/jdk/test/javax/net/ssl/FixingJavadocs/ImplicitHandshake.java
@@ -55,7 +55,7 @@ public class ImplicitHandshake {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/JavaxURLNulls.java b/jdk/test/javax/net/ssl/FixingJavadocs/JavaxURLNulls.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/JavaxURLNulls.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/JavaxURLNulls.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/KMTMGetNothing.java b/jdk/test/javax/net/ssl/FixingJavadocs/KMTMGetNothing.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/KMTMGetNothing.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/KMTMGetNothing.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java b/jdk/test/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java
index fc9cfbf1071..e9338cc42eb 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java
+++ b/jdk/test/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java
@@ -55,7 +55,7 @@ public class SSLSessionNulls {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java b/jdk/test/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java
rename to jdk/test/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java
index 2e3f544d246..bf1e757ed6a 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java
+++ b/jdk/test/javax/net/ssl/FixingJavadocs/SSLSocketInherit.java
@@ -38,7 +38,7 @@ import java.net.*;
 import javax.net.ssl.*;
 
 public class SSLSocketInherit {
-    String pathToStores = "../../../../etc";
+    String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java b/jdk/test/javax/net/ssl/GetInstance.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java
rename to jdk/test/javax/net/ssl/GetInstance.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/CriticalSubjectAltName.java b/jdk/test/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/CriticalSubjectAltName.java
rename to jdk/test/javax/net/ssl/HttpsURLConnection/CriticalSubjectAltName.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/HttpsURLConnection/DelayDefaultContextLoading.java b/jdk/test/javax/net/ssl/HttpsURLConnection/DelayDefaultContextLoading.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/HttpsURLConnection/DelayDefaultContextLoading.java
rename to jdk/test/javax/net/ssl/HttpsURLConnection/DelayDefaultContextLoading.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/GetResponseCode.java b/jdk/test/javax/net/ssl/HttpsURLConnection/GetResponseCode.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/GetResponseCode.java
rename to jdk/test/javax/net/ssl/HttpsURLConnection/GetResponseCode.java
index 9335085eeba..87ffef9c0f8 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/GetResponseCode.java
+++ b/jdk/test/javax/net/ssl/HttpsURLConnection/GetResponseCode.java
@@ -54,7 +54,7 @@ public class GetResponseCode implements HostnameVerifier {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/crisubn.jks b/jdk/test/javax/net/ssl/HttpsURLConnection/crisubn.jks
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/crisubn.jks
rename to jdk/test/javax/net/ssl/HttpsURLConnection/crisubn.jks
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/trusted.jks b/jdk/test/javax/net/ssl/HttpsURLConnection/trusted.jks
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/trusted.jks
rename to jdk/test/javax/net/ssl/HttpsURLConnection/trusted.jks
diff --git a/jdk/test/sun/security/ssl/README b/jdk/test/javax/net/ssl/README
similarity index 100%
rename from jdk/test/sun/security/ssl/README
rename to jdk/test/javax/net/ssl/README
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/AcceptLargeFragments.java b/jdk/test/javax/net/ssl/SSLEngine/AcceptLargeFragments.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/AcceptLargeFragments.java
rename to jdk/test/javax/net/ssl/SSLEngine/AcceptLargeFragments.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ArgCheck.java b/jdk/test/javax/net/ssl/SSLEngine/ArgCheck.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ArgCheck.java
rename to jdk/test/javax/net/ssl/SSLEngine/ArgCheck.java
index be395db8a90..3b94c6e2992 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ArgCheck.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/ArgCheck.java
@@ -40,7 +40,7 @@ public class ArgCheck {
 
     private static boolean debug = false;
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Arrays.java b/jdk/test/javax/net/ssl/SSLEngine/Arrays.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Arrays.java
rename to jdk/test/javax/net/ssl/SSLEngine/Arrays.java
index cae1e552040..ed75a4555c7 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Arrays.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/Arrays.java
@@ -42,7 +42,7 @@ public class Arrays {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java b/jdk/test/javax/net/ssl/SSLEngine/Basics.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java
rename to jdk/test/javax/net/ssl/SSLEngine/Basics.java
index 9f73c8dccf5..8c17e735c55 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Basics.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/Basics.java
@@ -43,7 +43,7 @@ import javax.net.ssl.SSLEngineResult.*;
 
 public class Basics {
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java b/jdk/test/javax/net/ssl/SSLEngine/CheckStatus.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java
rename to jdk/test/javax/net/ssl/SSLEngine/CheckStatus.java
index dfdefa9f1f7..c7133ef5d43 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/CheckStatus.java
@@ -48,7 +48,7 @@ public class CheckStatus {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java b/jdk/test/javax/net/ssl/SSLEngine/ConnectionTest.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java
rename to jdk/test/javax/net/ssl/SSLEngine/ConnectionTest.java
index 546a7865668..cdc9bcaa08c 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/ConnectionTest.java
@@ -47,7 +47,7 @@ public class ConnectionTest {
     private SSLEngine ssle1;
     private SSLEngine ssle2;
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeyEngine.java b/jdk/test/javax/net/ssl/SSLEngine/ExtendedKeyEngine.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeyEngine.java
rename to jdk/test/javax/net/ssl/SSLEngine/ExtendedKeyEngine.java
index ca109392866..2067467b78f 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeyEngine.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/ExtendedKeyEngine.java
@@ -42,7 +42,7 @@ public class ExtendedKeyEngine {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeySocket.java b/jdk/test/javax/net/ssl/SSLEngine/ExtendedKeySocket.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeySocket.java
rename to jdk/test/javax/net/ssl/SSLEngine/ExtendedKeySocket.java
index 0f5b54bf1da..ef4eef3a330 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeySocket.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/ExtendedKeySocket.java
@@ -55,7 +55,7 @@ public class ExtendedKeySocket {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static char [] passwd = "passphrase".toCharArray();
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargeBufs.java b/jdk/test/javax/net/ssl/SSLEngine/LargeBufs.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargeBufs.java
rename to jdk/test/javax/net/ssl/SSLEngine/LargeBufs.java
index 5960ea63992..af7f7a146dc 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargeBufs.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/LargeBufs.java
@@ -50,7 +50,7 @@ public class LargeBufs {
     static private SSLEngine ssle1;     // client
     static private SSLEngine ssle2;     // server
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java b/jdk/test/javax/net/ssl/SSLEngine/LargePacket.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java
rename to jdk/test/javax/net/ssl/SSLEngine/LargePacket.java
index c95ebfdf7dc..33f2c4f49ba 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/LargePacket.java
@@ -174,7 +174,7 @@ public class LargePacket extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     LargePacket() throws Exception {
-        super("../../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/MyX509ExtendedKeyManager.java b/jdk/test/javax/net/ssl/SSLEngine/MyX509ExtendedKeyManager.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/MyX509ExtendedKeyManager.java
rename to jdk/test/javax/net/ssl/SSLEngine/MyX509ExtendedKeyManager.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/MyX509KeyManager.java b/jdk/test/javax/net/ssl/SSLEngine/MyX509KeyManager.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/MyX509KeyManager.java
rename to jdk/test/javax/net/ssl/SSLEngine/MyX509KeyManager.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java b/jdk/test/javax/net/ssl/SSLEngine/NoAuthClientAuth.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java
rename to jdk/test/javax/net/ssl/SSLEngine/NoAuthClientAuth.java
index f951e84c8bc..db8c091c115 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/NoAuthClientAuth.java
@@ -117,7 +117,7 @@ public class NoAuthClientAuth {
     /*
      * The following is to set up the keystores.
      */
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineResultArgs.java b/jdk/test/javax/net/ssl/SSLEngine/SSLEngineResultArgs.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineResultArgs.java
rename to jdk/test/javax/net/ssl/SSLEngine/SSLEngineResultArgs.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java b/jdk/test/javax/net/ssl/SSLEngine/SSLEngineService.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java
rename to jdk/test/javax/net/ssl/SSLEngine/SSLEngineService.java
index bc4c6f7db12..d3ee14666c5 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineService.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/SSLEngineService.java
@@ -49,7 +49,7 @@ public class SSLEngineService {
     private String trustFilename;
 
     protected SSLEngineService() {
-        init("../../../../../etc");
+        init("../etc");
     }
 
     protected SSLEngineService(String pathToStores) {
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java b/jdk/test/javax/net/ssl/SSLEngine/TestAllSuites.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java
rename to jdk/test/javax/net/ssl/SSLEngine/TestAllSuites.java
index 9781614318d..9c633b58f70 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java
+++ b/jdk/test/javax/net/ssl/SSLEngine/TestAllSuites.java
@@ -51,7 +51,7 @@ public class TestAllSuites {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../etc";
+    private static String pathToStores = "../etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngineResult/Deserialize.java b/jdk/test/javax/net/ssl/SSLEngineResult/Deserialize.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngineResult/Deserialize.java
rename to jdk/test/javax/net/ssl/SSLEngineResult/Deserialize.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java b/jdk/test/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
rename to jdk/test/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
index c25d74c7d2c..2c2bae510e5 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
+++ b/jdk/test/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
@@ -57,7 +57,7 @@ public class UseCipherSuitesOrder {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/SSLServerSocket/DefaultSSLServSocketFac.java b/jdk/test/javax/net/ssl/SSLServerSocket/DefaultSSLServSocketFac.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/SSLServerSocket/DefaultSSLServSocketFac.java
rename to jdk/test/javax/net/ssl/SSLServerSocket/DefaultSSLServSocketFac.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java b/jdk/test/javax/net/ssl/SSLSession/CheckMyTrustedKeystore.java
similarity index 97%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java
rename to jdk/test/javax/net/ssl/SSLSession/CheckMyTrustedKeystore.java
index 7dee02ea699..422d88debd1 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/CheckMyTrustedKeystore.java
+++ b/jdk/test/javax/net/ssl/SSLSession/CheckMyTrustedKeystore.java
@@ -21,21 +21,23 @@
  * questions.
  */
 
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
 /*
  * @test
  * @bug 4329114
  * @summary Need better way of reflecting the reason when a chain is
  *      rejected as untrusted.
+ * @ignore JSSE supports algorithm constraints with CR 6916074,
+ *      need to update this test case in JDK 7 soon
  * @run main/othervm CheckMyTrustedKeystore
  *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
- * @ignore JSSE supports algorithm constraints with CR 6916074,
- *     need to update this test case in JDK 7 soon
- * This is a serious hack job!
  * @author Brad Wetmore
  */
 
+// This is a serious hack job!
+
 import java.io.*;
 import java.net.*;
 import java.security.*;
@@ -60,7 +62,7 @@ public class CheckMyTrustedKeystore {
     /*
      * Where do we find the keystores?
      */
-    final static String pathToStores = "../../../../etc";
+    final static String pathToStores = "../etc";
     final static String keyStoreFile = "keystore";
     final static String trustStoreFile = "truststore";
     final static String unknownStoreFile = "unknown_keystore";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/HttpsURLConnectionLocalCertificateChain.java b/jdk/test/javax/net/ssl/SSLSession/HttpsURLConnectionLocalCertificateChain.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/HttpsURLConnectionLocalCertificateChain.java
rename to jdk/test/javax/net/ssl/SSLSession/HttpsURLConnectionLocalCertificateChain.java
index ec773b244dd..c6e9753a2c1 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/HttpsURLConnectionLocalCertificateChain.java
+++ b/jdk/test/javax/net/ssl/SSLSession/HttpsURLConnectionLocalCertificateChain.java
@@ -62,7 +62,7 @@ public class HttpsURLConnectionLocalCertificateChain
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java b/jdk/test/javax/net/ssl/SSLSession/JSSERenegotiate.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java
rename to jdk/test/javax/net/ssl/SSLSession/JSSERenegotiate.java
index 748b5fed6d4..40617bfd321 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/JSSERenegotiate.java
+++ b/jdk/test/javax/net/ssl/SSLSession/JSSERenegotiate.java
@@ -63,7 +63,7 @@ public class JSSERenegotiate {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/KeyManagerTrustManager.java b/jdk/test/javax/net/ssl/SSLSession/KeyManagerTrustManager.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/KeyManagerTrustManager.java
rename to jdk/test/javax/net/ssl/SSLSession/KeyManagerTrustManager.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLCtxAccessToSessCtx.java b/jdk/test/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLCtxAccessToSessCtx.java
rename to jdk/test/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java
index 41fddc46ed0..14ed3eab716 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SSLCtxAccessToSessCtx.java
+++ b/jdk/test/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java
@@ -55,7 +55,7 @@ public class SSLCtxAccessToSessCtx  {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java b/jdk/test/javax/net/ssl/SSLSession/SessionCacheSizeTests.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java
rename to jdk/test/javax/net/ssl/SSLSession/SessionCacheSizeTests.java
index d4e00855dc6..4001f83ed47 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java
+++ b/jdk/test/javax/net/ssl/SSLSession/SessionCacheSizeTests.java
@@ -70,7 +70,7 @@ public class SessionCacheSizeTests {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java b/jdk/test/javax/net/ssl/SSLSession/SessionTimeOutTests.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java
rename to jdk/test/javax/net/ssl/SSLSession/SessionTimeOutTests.java
index 9264cb08723..98e590799c8 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java
+++ b/jdk/test/javax/net/ssl/SSLSession/SessionTimeOutTests.java
@@ -69,7 +69,7 @@ public class SessionTimeOutTests {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/testEnabledProtocols.java b/jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/testEnabledProtocols.java
rename to jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java
index 5774049ba6e..0e6e8b197c8 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/testEnabledProtocols.java
+++ b/jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java
@@ -99,7 +99,7 @@ public class testEnabledProtocols {
     /*
      * Where do we find the keystores?
      */
-    final static String pathToStores = "../../../../etc";
+    final static String pathToStores = "../etc";
     static String passwd = "passphrase";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java b/jdk/test/javax/net/ssl/ServerName/IllegalSNIName.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java
rename to jdk/test/javax/net/ssl/ServerName/IllegalSNIName.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorer.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java
rename to jdk/test/javax/net/ssl/ServerName/SSLEngineExplorer.java
index 2cd46354010..a7831316d0c 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorer.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../NewAPIs/SSLEngine ../../../../templates
+ * @library ../SSLEngine ../templates
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorer SSLv2Hello,SSLv3
  * @run main/othervm SSLEngineExplorer SSLv3
@@ -251,7 +251,7 @@ public class SSLEngineExplorer extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     SSLEngineExplorer() throws Exception {
-        super("../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
index c201bee86ad..b9854dd3e94 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../NewAPIs/SSLEngine ../../../../templates
+ * @library ../SSLEngine ../templates
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerMatchedSNI www.example.com
  *     www\.example\.com
@@ -309,7 +309,7 @@ public class SSLEngineExplorerMatchedSNI extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     SSLEngineExplorerMatchedSNI() throws Exception {
-        super("../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
index 2a9647be457..ff8678ba6a8 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../NewAPIs/SSLEngine ../../../../templates
+ * @library ../SSLEngine ../templates
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerUnmatchedSNI www.example.com
  *                                                 www\.example\.org
@@ -322,7 +322,7 @@ public class SSLEngineExplorerUnmatchedSNI extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     SSLEngineExplorerUnmatchedSNI() throws Exception {
-        super("../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
rename to jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
index bfa23cb38de..f9888839929 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../NewAPIs/SSLEngine ../../../../templates
+ * @library ../SSLEngine ../templates
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerWithCli
  */
@@ -281,7 +281,7 @@ public class SSLEngineExplorerWithCli extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     SSLEngineExplorerWithCli() throws Exception {
-        super("../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
rename to jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
index e8fd2707f25..0517a7750aa 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../NewAPIs/SSLEngine ../../../../templates
+ * @library ../SSLEngine ../templates
  * @build SSLEngineService SSLCapabilities SSLExplorer
  * @run main/othervm SSLEngineExplorerWithSrv
  */
@@ -267,7 +267,7 @@ public class SSLEngineExplorerWithSrv extends SSLEngineService {
      * Fork off the other side, then do your work.
      */
     SSLEngineExplorerWithSrv() throws Exception {
-        super("../../../../etc");
+        super("../etc");
 
         if (separateServerThread) {
             startServer(true);
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
index d9ff691e06c..38d999aa3ef 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
@@ -58,7 +58,7 @@ public class SSLSocketConsistentSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorer.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorer.java
index 27e2b6abce7..a91697c5915 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorer.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorer.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorer SSLv2Hello,SSLv3
  * @run main/othervm SSLSocketExplorer SSLv3
@@ -64,7 +64,7 @@ public class SSLSocketExplorer {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
index 44a37150ef8..aaf8d299486 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerFailure SSLv2Hello,SSLv3
  * @run main/othervm SSLSocketExplorerFailure SSLv3
@@ -64,7 +64,7 @@ public class SSLSocketExplorerFailure {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
index c9ae26c42a6..724a37e1a80 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerMatchedSNI www.example.com
  *     www\.example\.com
@@ -69,7 +69,7 @@ public class SSLSocketExplorerMatchedSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
index eab48002d6f..732e0cf3097 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerUnmatchedSNI www.example.com
  *                                                 www\.example\.org
@@ -61,7 +61,7 @@ public class SSLSocketExplorerUnmatchedSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
index 6933c9a9894..8f2b7816864 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerWithCliSNI
  */
@@ -60,7 +60,7 @@ public class SSLSocketExplorerWithCliSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
index 64b1ae9a63b..f026f32e781 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java
@@ -30,7 +30,7 @@
  * @test
  * @bug 7068321
  * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server
- * @library ../../../../templates
+ * @library ../templates
  * @build SSLCapabilities SSLExplorer
  * @run main/othervm SSLSocketExplorerWithSrvSNI
  */
@@ -60,7 +60,7 @@ public class SSLSocketExplorerWithSrvSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
index 6ba1dfd9c21..7c54dd1a882 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
+++ b/jdk/test/javax/net/ssl/ServerName/SSLSocketInconsistentSNI.java
@@ -58,7 +58,7 @@ public class SSLSocketInconsistentSNI {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java b/jdk/test/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
rename to jdk/test/javax/net/ssl/ServerName/SSLSocketSNISensitive.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java b/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
rename to jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
index 3b11d2a59a7..572ac2cce8c 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
+++ b/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
@@ -60,7 +60,7 @@ public class EmptyCertificateAuthorities {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableBlockCipher.java b/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableBlockCipher.java
rename to jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
index ad27a1e468f..cb232a00e19 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableBlockCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
@@ -57,7 +57,7 @@ public class ExportableBlockCipher {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableStreamCipher.java b/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableStreamCipher.java
rename to jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
index 3d15a7cf154..572d9893b85 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/ExportableStreamCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
@@ -57,7 +57,7 @@ public class ExportableStreamCipher {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericBlockCipher.java b/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericBlockCipher.java
rename to jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
index 9a0a83e26e4..5f851843ffb 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericBlockCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
@@ -57,7 +57,7 @@ public class GenericBlockCipher {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericStreamCipher.java b/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
similarity index 99%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericStreamCipher.java
rename to jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
index c96d8ec9cc8..4cf02417e82 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv11/GenericStreamCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
@@ -57,7 +57,7 @@ public class GenericStreamCipher {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../etc";
+    static String pathToStores = "../etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java b/jdk/test/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java
rename to jdk/test/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java b/jdk/test/javax/net/ssl/TLSv12/ShortRSAKey512.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java
rename to jdk/test/javax/net/ssl/TLSv12/ShortRSAKey512.java
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java b/jdk/test/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java
similarity index 100%
rename from jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java
rename to jdk/test/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java
diff --git a/jdk/test/sun/security/ssl/etc/keystore b/jdk/test/javax/net/ssl/etc/keystore
similarity index 100%
rename from jdk/test/sun/security/ssl/etc/keystore
rename to jdk/test/javax/net/ssl/etc/keystore
diff --git a/jdk/test/sun/security/ssl/etc/truststore b/jdk/test/javax/net/ssl/etc/truststore
similarity index 100%
rename from jdk/test/sun/security/ssl/etc/truststore
rename to jdk/test/javax/net/ssl/etc/truststore
diff --git a/jdk/test/sun/security/ssl/etc/unknown_keystore b/jdk/test/javax/net/ssl/etc/unknown_keystore
similarity index 100%
rename from jdk/test/sun/security/ssl/etc/unknown_keystore
rename to jdk/test/javax/net/ssl/etc/unknown_keystore
diff --git a/jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java b/jdk/test/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java
rename to jdk/test/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java
diff --git a/jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java b/jdk/test/javax/net/ssl/sanity/ciphersuites/CipherSuitesInOrder.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java
rename to jdk/test/javax/net/ssl/sanity/ciphersuites/CipherSuitesInOrder.java
diff --git a/jdk/test/sun/security/ssl/sanity/ciphersuites/NoKerberos.java b/jdk/test/javax/net/ssl/sanity/ciphersuites/NoKerberos.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/ciphersuites/NoKerberos.java
rename to jdk/test/javax/net/ssl/sanity/ciphersuites/NoKerberos.java
diff --git a/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java b/jdk/test/javax/net/ssl/sanity/interop/CipherTest.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/interop/CipherTest.java
rename to jdk/test/javax/net/ssl/sanity/interop/CipherTest.java
diff --git a/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java b/jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
rename to jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java
diff --git a/jdk/test/sun/security/ssl/sanity/interop/JSSEClient.java b/jdk/test/javax/net/ssl/sanity/interop/JSSEClient.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/interop/JSSEClient.java
rename to jdk/test/javax/net/ssl/sanity/interop/JSSEClient.java
diff --git a/jdk/test/sun/security/ssl/sanity/interop/JSSEServer.java b/jdk/test/javax/net/ssl/sanity/interop/JSSEServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/interop/JSSEServer.java
rename to jdk/test/javax/net/ssl/sanity/interop/JSSEServer.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/CheckSSLContextExport.java b/jdk/test/javax/net/ssl/sanity/pluggability/CheckSSLContextExport.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/CheckSSLContextExport.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/CheckSSLContextExport.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/CheckSockFacExport1.java b/jdk/test/javax/net/ssl/sanity/pluggability/CheckSockFacExport1.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/CheckSockFacExport1.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/CheckSockFacExport1.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/CheckSockFacExport2.java b/jdk/test/javax/net/ssl/sanity/pluggability/CheckSockFacExport2.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/CheckSockFacExport2.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/CheckSockFacExport2.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/CipherSuites.java b/jdk/test/javax/net/ssl/sanity/pluggability/CipherSuites.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/CipherSuites.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/CipherSuites.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/MySSLContextImpl.java b/jdk/test/javax/net/ssl/sanity/pluggability/MySSLContextImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/MySSLContextImpl.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/MySSLContextImpl.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/MySSLEngineImpl.java b/jdk/test/javax/net/ssl/sanity/pluggability/MySSLEngineImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/MySSLEngineImpl.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/MySSLEngineImpl.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/MySSLServerSocketFacImpl.java b/jdk/test/javax/net/ssl/sanity/pluggability/MySSLServerSocketFacImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/MySSLServerSocketFacImpl.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/MySSLServerSocketFacImpl.java
diff --git a/jdk/test/sun/security/ssl/sanity/pluggability/MySSLSocketFacImpl.java b/jdk/test/javax/net/ssl/sanity/pluggability/MySSLSocketFacImpl.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sanity/pluggability/MySSLSocketFacImpl.java
rename to jdk/test/javax/net/ssl/sanity/pluggability/MySSLSocketFacImpl.java
diff --git a/jdk/test/sun/security/ssl/templates/SSLCapabilities.java b/jdk/test/javax/net/ssl/templates/SSLCapabilities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/templates/SSLCapabilities.java
rename to jdk/test/javax/net/ssl/templates/SSLCapabilities.java
diff --git a/jdk/test/sun/security/ssl/templates/SSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java
similarity index 100%
rename from jdk/test/sun/security/ssl/templates/SSLEngineTemplate.java
rename to jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java
diff --git a/jdk/test/sun/security/ssl/templates/SSLExplorer.java b/jdk/test/javax/net/ssl/templates/SSLExplorer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/templates/SSLExplorer.java
rename to jdk/test/javax/net/ssl/templates/SSLExplorer.java
diff --git a/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java
similarity index 99%
rename from jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java
rename to jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java
index d61a1e5345e..e82fd6402fd 100644
--- a/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java
+++ b/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java
@@ -124,7 +124,7 @@ public class SSLSocketSSLEngineTemplate {
     /*
      * The following is to set up the keystores/trust material.
      */
-    private static final String pathToStores = "../etc/";
+    private static final String pathToStores = "../etc";
     private static final String keyStoreFile = "keystore";
     private static final String trustStoreFile = "truststore";
     private static final String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/templates/SSLSocketTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java
similarity index 100%
rename from jdk/test/sun/security/ssl/templates/SSLSocketTemplate.java
rename to jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/httpstest/AbstractCallback.java b/jdk/test/sun/net/www/protocol/https/AbstractCallback.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/httpstest/AbstractCallback.java
rename to jdk/test/sun/net/www/protocol/https/AbstractCallback.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/http/ChunkedOutputStream/Test.java b/jdk/test/sun/net/www/protocol/https/ChunkedOutputStream.java
similarity index 97%
rename from jdk/test/sun/security/ssl/sun/net/www/http/ChunkedOutputStream/Test.java
rename to jdk/test/sun/net/www/protocol/https/ChunkedOutputStream.java
index 67fe5c229f7..cce270642ce 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/http/ChunkedOutputStream/Test.java
+++ b/jdk/test/sun/net/www/protocol/https/ChunkedOutputStream.java
@@ -26,7 +26,7 @@
  * @bug 5026745
  * @library ../../httpstest/
  * @build TestHttpsServer HttpCallback
- * @run main/othervm Test
+ * @run main/othervm ChunkedOutputStream
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
  *     system properties in samevm/agentvm mode.
@@ -37,11 +37,11 @@ import java.io.*;
 import java.net.*;
 import javax.net.ssl.*;
 
-public class Test implements HttpCallback {
+public class ChunkedOutputStream implements HttpCallback {
     /*
      * Where do we find the keystores for ssl?
      */
-    static String pathToStores = "../../../../../etc";
+    static String pathToStores = "../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
@@ -297,7 +297,8 @@ public class Test implements HttpCallback {
             HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
 
             try {
-                server = new TestHttpsServer (new Test(), 1, 10, 0);
+                server = new TestHttpsServer(
+                        new ChunkedOutputStream(), 1, 10, 0);
                 System.out.println ("Server started: listening on port: " + server.getLocalPort());
                 // the test server doesn't support keep-alive yet
                 // test1("http://localhost:"+server.getLocalPort()+"/d0");
diff --git a/jdk/test/sun/security/ssl/sun/net/www/httpstest/ClosedChannelList.java b/jdk/test/sun/net/www/protocol/https/ClosedChannelList.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/httpstest/ClosedChannelList.java
rename to jdk/test/sun/net/www/protocol/https/ClosedChannelList.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/httpstest/HttpCallback.java b/jdk/test/sun/net/www/protocol/https/HttpCallback.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/httpstest/HttpCallback.java
rename to jdk/test/sun/net/www/protocol/https/HttpCallback.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/httpstest/HttpTransaction.java b/jdk/test/sun/net/www/protocol/https/HttpTransaction.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/httpstest/HttpTransaction.java
rename to jdk/test/sun/net/www/protocol/https/HttpTransaction.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/MyKeyManager.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/MyKeyManager.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/MyKeyManager.java
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/MyKeyManager.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/OriginServer.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/OriginServer.java
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyAuthTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyAuthTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java
index a4ef930ff64..8fa75aa81c2 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyAuthTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java
@@ -50,7 +50,7 @@ public class ProxyAuthTest {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyTunnelServer.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ServerIdentityTest.java b/jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ServerIdentityTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/dnsstore b/jdk/test/sun/net/www/protocol/https/HttpsClient/dnsstore
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/dnsstore
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/dnsstore
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ipstore b/jdk/test/sun/net/www/protocol/https/HttpsClient/ipstore
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ipstore
rename to jdk/test/sun/net/www/protocol/https/HttpsClient/ipstore
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java
similarity index 98%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java
index 4df22a85c45..a5992579025 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6216082
- * @library ../../../httpstest/
+ * @library ..
  * @build HttpCallback TestHttpsServer ClosedChannelList HttpTransaction TunnelProxy
  * @summary  Redirect problem with HttpsURLConnection using a proxy
  *     SunJSSE does not support dynamic system properties, no way to re-use
@@ -83,7 +83,7 @@ public class B6216082 {
     /*
      * Where do we find the keystores for ssl?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CheckMethods.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CheckMethods.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CheckMethods.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CheckMethods.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
index c025c6ef1b9..559f7af98ce 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CloseKeepAliveCached.java
@@ -62,7 +62,7 @@ public class CloseKeepAliveCached {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java
index 2e7d3fb8843..565138c143d 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java
@@ -56,7 +56,7 @@ public class CookieHandlerTest {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java
index 21006f0803d..82b54dfd08b 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java
@@ -69,7 +69,7 @@ public class CookieHttpsClientTest {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/DNSIdentities.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java
index 08d969d0579..a7e0bc3ab14 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java
@@ -63,7 +63,7 @@ public class HttpsCreateSockTest
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java
index 8d265f11c3a..7964234dbfd 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsPost.java
@@ -54,7 +54,7 @@ public class HttpsPost {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
index 043f612cf3c..4011cea722e 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
@@ -63,7 +63,7 @@ public class HttpsSocketFacTest
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/Identities.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/Identities.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/Identities.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/Identities.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/OriginServer.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/OriginServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/OriginServer.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/OriginServer.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java
index 3908db8ce1b..2ad8a0fde0b 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java
@@ -45,7 +45,7 @@ public class PostThruProxy {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java
index d3e7ddae4ff..1a505ac1f34 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.java
@@ -46,7 +46,7 @@ public class PostThruProxyWithAuth {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java
index cfaaeb456fe..834d984cc6a 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java
@@ -55,7 +55,7 @@ public class ReadTimeout {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java
index 276f96c6d25..eacabdd9961 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/Redirect.java
@@ -54,7 +54,7 @@ public class Redirect {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java
index c665af0fda7..a21c1b061e8 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/RetryHttps.java
@@ -56,7 +56,7 @@ public class RetryHttps {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java
rename to jdk/test/sun/net/www/protocol/https/HttpsURLConnection/TunnelProxy.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java
rename to jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java
index 4149bd4be12..ce6f59c8909 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java
+++ b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHTTPSConnection.java
@@ -61,7 +61,7 @@ public class ComHTTPSConnection {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java b/jdk/test/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java
rename to jdk/test/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java b/jdk/test/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java
similarity index 99%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java
rename to jdk/test/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java
index 06b0162b570..196f1d4bf0f 100644
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java
+++ b/jdk/test/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java
@@ -59,7 +59,7 @@ public class JavaxHTTPSConnection {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../etc";
+    static String pathToStores = "../../../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java b/jdk/test/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java
rename to jdk/test/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java
diff --git a/jdk/test/sun/security/ssl/sun/net/www/httpstest/TestHttpsServer.java b/jdk/test/sun/net/www/protocol/https/TestHttpsServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/sun/net/www/httpstest/TestHttpsServer.java
rename to jdk/test/sun/net/www/protocol/https/TestHttpsServer.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadBlocksClose.java b/jdk/test/sun/security/ssl/AppInputStream/ReadBlocksClose.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadBlocksClose.java
rename to jdk/test/sun/security/ssl/AppInputStream/ReadBlocksClose.java
index e14976ce777..b6e83da5cfe 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadBlocksClose.java
+++ b/jdk/test/sun/security/ssl/AppInputStream/ReadBlocksClose.java
@@ -54,7 +54,7 @@ public class ReadBlocksClose {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadHandshake.java b/jdk/test/sun/security/ssl/AppInputStream/ReadHandshake.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadHandshake.java
rename to jdk/test/sun/security/ssl/AppInputStream/ReadHandshake.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadZeroBytes.java b/jdk/test/sun/security/ssl/AppInputStream/ReadZeroBytes.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadZeroBytes.java
rename to jdk/test/sun/security/ssl/AppInputStream/ReadZeroBytes.java
index 566fdc034a3..931f07dfa2d 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/ReadZeroBytes.java
+++ b/jdk/test/sun/security/ssl/AppInputStream/ReadZeroBytes.java
@@ -53,7 +53,7 @@ public class ReadZeroBytes {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/RemoveMarkReset.java b/jdk/test/sun/security/ssl/AppInputStream/RemoveMarkReset.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/RemoveMarkReset.java
rename to jdk/test/sun/security/ssl/AppInputStream/RemoveMarkReset.java
index 096f12f8a87..819b1744e58 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppInputStream/RemoveMarkReset.java
+++ b/jdk/test/sun/security/ssl/AppInputStream/RemoveMarkReset.java
@@ -54,7 +54,7 @@ public class RemoveMarkReset {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppOutputStream/NoExceptionOnClose.java b/jdk/test/sun/security/ssl/AppOutputStream/NoExceptionOnClose.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppOutputStream/NoExceptionOnClose.java
rename to jdk/test/sun/security/ssl/AppOutputStream/NoExceptionOnClose.java
index a085d47ff04..f6c129e9bba 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/AppOutputStream/NoExceptionOnClose.java
+++ b/jdk/test/sun/security/ssl/AppOutputStream/NoExceptionOnClose.java
@@ -54,7 +54,7 @@ public class NoExceptionOnClose {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/CipherSuite/SSL_NULL.java b/jdk/test/sun/security/ssl/CipherSuite/SSL_NULL.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/CipherSuite/SSL_NULL.java
rename to jdk/test/sun/security/ssl/CipherSuite/SSL_NULL.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/CipherSuiteOrder.java b/jdk/test/sun/security/ssl/ClientHandshaker/CipherSuiteOrder.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/CipherSuiteOrder.java
rename to jdk/test/sun/security/ssl/ClientHandshaker/CipherSuiteOrder.java
index 75e7436291f..5276fcba027 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/CipherSuiteOrder.java
+++ b/jdk/test/sun/security/ssl/ClientHandshaker/CipherSuiteOrder.java
@@ -55,7 +55,7 @@ public class CipherSuiteOrder {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/RSAExport.java b/jdk/test/sun/security/ssl/ClientHandshaker/RSAExport.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/RSAExport.java
rename to jdk/test/sun/security/ssl/ClientHandshaker/RSAExport.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java b/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java
rename to jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.java b/jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.java
rename to jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java
index fc6eafa259a..6fff6db076d 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.java
+++ b/jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.java
@@ -114,7 +114,7 @@ public class DebugReportsOneExtraByte {
     /*
      * The following is to set up the keystores.
      */
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh b/jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.sh
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh
rename to jdk/test/sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.sh
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ClientThread.java b/jdk/test/sun/security/ssl/GenSSLConfigs/ClientThread.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ClientThread.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/ClientThread.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/Handler.java b/jdk/test/sun/security/ssl/GenSSLConfigs/Handler.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/Handler.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/Handler.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ServerHandler.java b/jdk/test/sun/security/ssl/GenSSLConfigs/ServerHandler.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ServerHandler.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/ServerHandler.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ServerThread.java b/jdk/test/sun/security/ssl/GenSSLConfigs/ServerThread.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/ServerThread.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/ServerThread.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/TestThread.java b/jdk/test/sun/security/ssl/GenSSLConfigs/TestThread.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/TestThread.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/TestThread.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/Traffic.java b/jdk/test/sun/security/ssl/GenSSLConfigs/Traffic.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/Traffic.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/Traffic.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/main.java b/jdk/test/sun/security/ssl/GenSSLConfigs/main.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/main.java
rename to jdk/test/sun/security/ssl/GenSSLConfigs/main.java
index dbe16292e04..13460595a81 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/main.java
+++ b/jdk/test/sun/security/ssl/GenSSLConfigs/main.java
@@ -188,11 +188,11 @@ public class main
         try {
             String testRoot = System.getProperty("test.src", ".");
             System.setProperty("javax.net.ssl.trustStore", testRoot
-                                + "/../../../../../../../etc/truststore");
+                                + "/../../../../javax/net/ssl/etc/truststore");
 
             KeyStore ks = KeyStore.getInstance("JKS");
             ks.load(new FileInputStream(testRoot
-                                + "/../../../../../../../etc/keystore"),
+                                + "/../../../../javax/net/ssl/etc/truststore"),
                     "passphrase".toCharArray());
             KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
             kmf.init(ks, "passphrase".toCharArray());
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/HandshakeOutStream/NullCerts.java b/jdk/test/sun/security/ssl/HandshakeOutStream/NullCerts.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/HandshakeOutStream/NullCerts.java
rename to jdk/test/sun/security/ssl/HandshakeOutStream/NullCerts.java
index 13b615456fc..51e37a0d5af 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/HandshakeOutStream/NullCerts.java
+++ b/jdk/test/sun/security/ssl/HandshakeOutStream/NullCerts.java
@@ -56,8 +56,7 @@ public class NullCerts {
     /*
      * Where do we find the keystores?
      */
-    // private final static String pathToStores = "./etc";
-    private final static String pathToStores = "../../../../../../../etc";
+    private final static String pathToStores = "../../../../javax/net/ssl/etc";
     private final static String keyStoreFile = "keystore";
     private final static String trustStoreFile = "truststore";
     private final static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/ClientHelloRead.java b/jdk/test/sun/security/ssl/InputRecord/ClientHelloRead.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/ClientHelloRead.java
rename to jdk/test/sun/security/ssl/InputRecord/ClientHelloRead.java
index f123a3cef87..e7a11bd205e 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/ClientHelloRead.java
+++ b/jdk/test/sun/security/ssl/InputRecord/ClientHelloRead.java
@@ -52,7 +52,7 @@ public class ClientHelloRead {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/OriginServer.java b/jdk/test/sun/security/ssl/InputRecord/OriginServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/OriginServer.java
rename to jdk/test/sun/security/ssl/InputRecord/OriginServer.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/ProxyTunnelServer.java b/jdk/test/sun/security/ssl/InputRecord/ProxyTunnelServer.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/ProxyTunnelServer.java
rename to jdk/test/sun/security/ssl/InputRecord/ProxyTunnelServer.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java b/jdk/test/sun/security/ssl/InputRecord/SSLSocketTimeoutNulls.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java
rename to jdk/test/sun/security/ssl/InputRecord/SSLSocketTimeoutNulls.java
index 4a72a1ecf1e..21218f5e4e1 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java
+++ b/jdk/test/sun/security/ssl/InputRecord/SSLSocketTimeoutNulls.java
@@ -58,7 +58,7 @@ public class SSLSocketTimeoutNulls {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ProtocolVersion/HttpsProtocols.java b/jdk/test/sun/security/ssl/ProtocolVersion/HttpsProtocols.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ProtocolVersion/HttpsProtocols.java
rename to jdk/test/sun/security/ssl/ProtocolVersion/HttpsProtocols.java
index bcdc16d4a3c..1190ece8397 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ProtocolVersion/HttpsProtocols.java
+++ b/jdk/test/sun/security/ssl/ProtocolVersion/HttpsProtocols.java
@@ -51,7 +51,7 @@ public class HttpsProtocols implements HostnameVerifier {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadKSProvider.java b/jdk/test/sun/security/ssl/SSLContextImpl/BadKSProvider.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadKSProvider.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/BadKSProvider.java
index 8e5f931e0a4..9fdc0797f94 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadKSProvider.java
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/BadKSProvider.java
@@ -53,7 +53,7 @@ public class BadKSProvider {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java b/jdk/test/sun/security/ssl/SSLContextImpl/BadTSProvider.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/BadTSProvider.java
index 93355acf93d..bf68126c4c9 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/BadTSProvider.java
@@ -53,7 +53,7 @@ public class BadTSProvider {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/CustomizedDefaultProtocols.java b/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedDefaultProtocols.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/CustomizedDefaultProtocols.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/CustomizedDefaultProtocols.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/DefaultEnabledProtocols.java b/jdk/test/sun/security/ssl/SSLContextImpl/DefaultEnabledProtocols.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/DefaultEnabledProtocols.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/DefaultEnabledProtocols.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/GoodProvider.java b/jdk/test/sun/security/ssl/SSLContextImpl/GoodProvider.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/GoodProvider.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/GoodProvider.java
index 0ca10ec0d8c..d97e5d35d7a 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/GoodProvider.java
+++ b/jdk/test/sun/security/ssl/SSLContextImpl/GoodProvider.java
@@ -53,7 +53,7 @@ public class GoodProvider {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/IllegalProtocolProperty.java b/jdk/test/sun/security/ssl/SSLContextImpl/IllegalProtocolProperty.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/IllegalProtocolProperty.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/IllegalProtocolProperty.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/NoOldVersionContext.java b/jdk/test/sun/security/ssl/SSLContextImpl/NoOldVersionContext.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/NoOldVersionContext.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/NoOldVersionContext.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/NullGetAcceptedIssuers.java b/jdk/test/sun/security/ssl/SSLContextImpl/NullGetAcceptedIssuers.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/NullGetAcceptedIssuers.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/NullGetAcceptedIssuers.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/SSLContextVersion.java b/jdk/test/sun/security/ssl/SSLContextImpl/SSLContextVersion.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/SSLContextVersion.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/SSLContextVersion.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java b/jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java
rename to jdk/test/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseEngineException.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/CloseEngineException.java
index 2acb9f96074..e68f9227396 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseEngineException.java
@@ -53,7 +53,7 @@ public class CloseEngineException {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseInboundException.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/CloseInboundException.java
index 178d94bc107..4b2c665e77f 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseInboundException.java
@@ -49,7 +49,7 @@ public class CloseInboundException {
     SSLEngineResult result1;    // ssle1's results from last operation
     SSLEngineResult result2;    // ssle2's results from last operation
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseStart.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/CloseStart.java
index a7cc6e254ca..96a992a675f 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/CloseStart.java
@@ -47,7 +47,7 @@ public class CloseStart {
 
     private static boolean debug = false;
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java b/jdk/test/sun/security/ssl/SSLEngineImpl/DelegatedTaskWrongException.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/DelegatedTaskWrongException.java
index 06366eb37b9..761f44c72c3 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/DelegatedTaskWrongException.java
@@ -47,7 +47,7 @@ public class DelegatedTaskWrongException {
     private SSLEngine ssle1;    // client
     private SSLEngine ssle2;    // server
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java b/jdk/test/sun/security/ssl/SSLEngineImpl/EmptyExtensionData.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/EmptyExtensionData.java
index 07ad31eb9e5..430785ecae4 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/EmptyExtensionData.java
@@ -43,7 +43,7 @@ public class EmptyExtensionData {
 
     private static boolean debug = false;
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java b/jdk/test/sun/security/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java
index 274f9394319..9ddf00e8f46 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java
@@ -52,7 +52,7 @@ public class EngineEnforceUseClientMode {
     private SSLEngine ssle4;    // server
     private SSLEngine ssle5;    // server
 
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java b/jdk/test/sun/security/ssl/SSLEngineImpl/RehandshakeFinished.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/RehandshakeFinished.java
index bcb4f2a8e56..4096ce083cf 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/RehandshakeFinished.java
@@ -129,7 +129,7 @@ public class RehandshakeFinished {
     /*
      * The following is to set up the keystores.
      */
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java b/jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
index 45a6df001e8..38d513632dc 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java
@@ -125,7 +125,7 @@ public class SSLEngineBadBufferArrayAccess {
     /*
      * The following is to set up the keystores/trust material.
      */
-    private static final String pathToStores = "../../../../../../../etc/";
+    private static final String pathToStores = "../../../../javax/net/ssl/etc";
     private static final String keyStoreFile = "keystore";
     private static final String trustStoreFile = "truststore";
     private static final String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java b/jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java
rename to jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java
index 0522226d987..27d89e22939 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java
+++ b/jdk/test/sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java
@@ -116,7 +116,7 @@ public class SSLEngineDeadlock {
     /*
      * The following is to set up the keystores.
      */
-    private static String pathToStores = "../../../../../../../etc";
+    private static String pathToStores = "../../../../javax/net/ssl/etc";
     private static String keyStoreFile = "keystore";
     private static String trustStoreFile = "truststore";
     private static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSessionContextImpl/Timeout.java b/jdk/test/sun/security/ssl/SSLSessionContextImpl/Timeout.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSessionContextImpl/Timeout.java
rename to jdk/test/sun/security/ssl/SSLSessionContextImpl/Timeout.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSessionImpl/HashCodeMissing.java b/jdk/test/sun/security/ssl/SSLSessionImpl/HashCodeMissing.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSessionImpl/HashCodeMissing.java
rename to jdk/test/sun/security/ssl/SSLSessionImpl/HashCodeMissing.java
index fa0433187f9..61f0c6cb477 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSessionImpl/HashCodeMissing.java
+++ b/jdk/test/sun/security/ssl/SSLSessionImpl/HashCodeMissing.java
@@ -55,7 +55,7 @@ public class HashCodeMissing {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java b/jdk/test/sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
index 8fb13107e90..27cc32dc589 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/AsyncSSLSocketClose.java
@@ -47,7 +47,7 @@ public class AsyncSSLSocketClose implements Runnable
     SSLServerSocket ss;
 
     // Where do we find the keystores?
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CheckMethods.java b/jdk/test/sun/security/ssl/SSLSocketImpl/CheckMethods.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CheckMethods.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/CheckMethods.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ClientModeClientAuth.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/ClientModeClientAuth.java
index 8f279e8c5bc..8f4ce4799fd 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientModeClientAuth.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ClientModeClientAuth.java
@@ -55,7 +55,7 @@ public class ClientModeClientAuth {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ClientTimeout.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/ClientTimeout.java
index 16d28193c75..c40b49a2d20 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ClientTimeout.java
@@ -55,7 +55,7 @@ public class ClientTimeout {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CloseSocket.java b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CloseSocket.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocket.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CloseSocketException.java b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocketException.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CloseSocketException.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocketException.java
index 41b88c1facd..b6e33a1324e 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/CloseSocketException.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/CloseSocketException.java
@@ -59,7 +59,7 @@ public class CloseSocketException {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java b/jdk/test/sun/security/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java
index 2a6f0a8fa56..6325b7c593f 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/InvalidateServerSessionRenegotiate.java
@@ -69,7 +69,7 @@ public class InvalidateServerSessionRenegotiate implements
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/LoopbackSSLSocket.java b/jdk/test/sun/security/ssl/SSLSocketImpl/LoopbackSSLSocket.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/LoopbackSSLSocket.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/LoopbackSSLSocket.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NewSocketMethods.java b/jdk/test/sun/security/ssl/SSLSocketImpl/NewSocketMethods.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NewSocketMethods.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NewSocketMethods.java
index b78154958c9..759a16609f5 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NewSocketMethods.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/NewSocketMethods.java
@@ -88,7 +88,7 @@ public class NewSocketMethods {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NoImpactServerRenego.java b/jdk/test/sun/security/ssl/SSLSocketImpl/NoImpactServerRenego.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NoImpactServerRenego.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NoImpactServerRenego.java
index ab23ce4239c..9c1a3394c75 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NoImpactServerRenego.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/NoImpactServerRenego.java
@@ -69,7 +69,7 @@ public class NoImpactServerRenego implements
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NonAutoClose.java b/jdk/test/sun/security/ssl/SSLSocketImpl/NonAutoClose.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NonAutoClose.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NonAutoClose.java
index 1d465e343c4..707d22e990e 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NonAutoClose.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/NonAutoClose.java
@@ -57,8 +57,7 @@ public class NonAutoClose {
     /*
      * Where do we find the keystores?
      */
-    // private final static String pathToStores = "./etc";
-    private final static String pathToStores = "../../../../../../../etc";
+    private final static String pathToStores = "../../../../javax/net/ssl/etc";
     private final static String keyStoreFile = "keystore";
     private final static String trustStoreFile = "truststore";
     private final static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.java b/jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.java
index 1cd8a53654e..bdc11f0e5a1 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.java
@@ -43,7 +43,7 @@ import java.security.*;
 
 public class NotifyHandshakeTest implements HandshakeCompletedListener {
 
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.policy b/jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh b/jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.sh
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.sh
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTestHeyYou.java b/jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTestHeyYou.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTestHeyYou.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTestHeyYou.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/RejectClientRenego.java b/jdk/test/sun/security/ssl/SSLSocketImpl/RejectClientRenego.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/RejectClientRenego.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/RejectClientRenego.java
index 01a7febca29..1a5d5e652d5 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/RejectClientRenego.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/RejectClientRenego.java
@@ -69,7 +69,7 @@ public class RejectClientRenego implements
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReuseAddr.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReuseAddr.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java
index db5209f9095..650c309887e 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReuseAddr.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java
@@ -54,7 +54,7 @@ public class ReuseAddr {
     /*
      * Where do we find the keystores?
      */
-    private final static String pathToStores = "../../../../../../../etc";
+    private final static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReverseNameLookup.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ReverseNameLookup.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReverseNameLookup.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/ReverseNameLookup.java
index 612712b35bf..0a0bf62f2cb 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ReverseNameLookup.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ReverseNameLookup.java
@@ -53,7 +53,7 @@ public class ReverseNameLookup {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java
index 1333561f7e6..616a3464eaf 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/SSLSocketImplThrowsWrongExceptions.java
@@ -57,7 +57,7 @@ public class SSLSocketImplThrowsWrongExceptions {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String passwd = "passphrase";
 
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ServerTimeout.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ServerTimeout.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ServerTimeout.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/ServerTimeout.java
index ff7c0db1203..39733204439 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ServerTimeout.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ServerTimeout.java
@@ -55,7 +55,7 @@ public class ServerTimeout {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "/../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SetClientMode.java b/jdk/test/sun/security/ssl/SSLSocketImpl/SetClientMode.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SetClientMode.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/SetClientMode.java
index f26ae0a0c7f..537e9337421 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/SetClientMode.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/SetClientMode.java
@@ -59,7 +59,7 @@ public class SetClientMode {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java b/jdk/test/sun/security/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java
rename to jdk/test/sun/security/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java
index 63fb43fa56b..b58a7ca255b 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java
+++ b/jdk/test/sun/security/ssl/SSLSocketImpl/UnconnectedSocketWrongExceptions.java
@@ -55,7 +55,7 @@ public class UnconnectedSocketWrongExceptions {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
rename to jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
index 137f11460a6..c546cfb7136 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
@@ -53,7 +53,7 @@ public class AnonCipherWithWantClientAuth {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHost.java b/jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHost.java
similarity index 96%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHost.java
rename to jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHost.java
index 2e4c9005429..96180df92be 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHost.java
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHost.java
@@ -40,7 +40,7 @@ public class GetPeerHost {
 
         String testRoot = System.getProperty("test.src", ".");
         System.setProperty("javax.net.ssl.trustStore", testRoot
-                            + "/../../../../../../../etc/truststore");
+                            + "/../../../../javax/net/ssl/etc/truststore");
         GetPeerHostServer server = new GetPeerHostServer();
         server.start();
         GetPeerHostClient client =
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostClient.java b/jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHostClient.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostClient.java
rename to jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHostClient.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostServer.java b/jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java
similarity index 97%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostServer.java
rename to jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java
index 5383052d167..afcaaf4b088 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ServerHandshaker/GetPeerHostServer.java
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java
@@ -53,7 +53,7 @@ class GetPeerHostServer extends Thread
             char[] passphrase = "passphrase".toCharArray();
             String testRoot = System.getProperty("test.src", ".");
             ks.load(new FileInputStream(testRoot
-                                        + "/../../../../../../../etc/keystore"),
+                        + "/../../../../javax/net/ssl/etc/keystore"),
                     passphrase);
             kmf.init(ks, passphrase);
             ctx.init(kmf.getKeyManagers(), null, null);
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SocketCreation/SocketCreation.java b/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SocketCreation/SocketCreation.java
rename to jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java
index f81675c3725..65e41b56ac2 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SocketCreation/SocketCreation.java
+++ b/jdk/test/sun/security/ssl/SocketCreation/SocketCreation.java
@@ -64,7 +64,7 @@ public class SocketCreation {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/NullCases.java b/jdk/test/sun/security/ssl/X509KeyManager/NullCases.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/NullCases.java
rename to jdk/test/sun/security/ssl/X509KeyManager/NullCases.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/PreferredKey.java b/jdk/test/sun/security/ssl/X509KeyManager/PreferredKey.java
similarity index 98%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/PreferredKey.java
rename to jdk/test/sun/security/ssl/X509KeyManager/PreferredKey.java
index 47e1e775856..0006090a866 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/PreferredKey.java
+++ b/jdk/test/sun/security/ssl/X509KeyManager/PreferredKey.java
@@ -50,7 +50,7 @@ public class PreferredKey {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String passwd = "passphrase";
 
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/SelectOneKeyOutOfMany.java b/jdk/test/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/SelectOneKeyOutOfMany.java
rename to jdk/test/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java
index 047ecfa0cdf..b0348fec841 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509KeyManager/SelectOneKeyOutOfMany.java
+++ b/jdk/test/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java
@@ -52,7 +52,7 @@ public class SelectOneKeyOutOfMany {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String passwd = "passphrase";
 
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CertRequestOverflow.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CertRequestOverflow.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java
index 883f9797d67..1c0c8d8c1c2 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CertRequestOverflow.java
+++ b/jdk/test/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java
@@ -59,7 +59,7 @@ public class CertRequestOverflow {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CheckNullEntity.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CheckNullEntity.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java
index 2f41c54021b..31f753fe543 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/CheckNullEntity.java
+++ b/jdk/test/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java
@@ -56,7 +56,7 @@ public class CheckNullEntity {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/ClientServer.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/ClientServer.java
index c6099b407b4..0bfd3317471 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java
+++ b/jdk/test/sun/security/ssl/X509TrustManagerImpl/ClientServer.java
@@ -62,7 +62,7 @@ public class ClientServer {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ComodoHacker.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ComodoHacker.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/SelfIssuedCert.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/SelfIssuedCert.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java
rename to jdk/test/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java
index d257d241ff9..d0eb242442e 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java
+++ b/jdk/test/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java
@@ -57,7 +57,7 @@ public class X509ExtendedTMEnabled {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/rsa/BrokenRSAPrivateCrtKey.java b/jdk/test/sun/security/ssl/rsa/BrokenRSAPrivateCrtKey.java
similarity index 100%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/rsa/BrokenRSAPrivateCrtKey.java
rename to jdk/test/sun/security/ssl/rsa/BrokenRSAPrivateCrtKey.java
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/spi/ProviderInit.java b/jdk/test/sun/security/ssl/spi/ProviderInit.java
similarity index 99%
rename from jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/spi/ProviderInit.java
rename to jdk/test/sun/security/ssl/spi/ProviderInit.java
index 682d80ade01..25ef93e921b 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/spi/ProviderInit.java
+++ b/jdk/test/sun/security/ssl/spi/ProviderInit.java
@@ -61,7 +61,7 @@ public class ProviderInit {
     /*
      * Where do we find the keystores?
      */
-    static String pathToStores = "../../../../../../../etc";
+    static String pathToStores = "../../../../javax/net/ssl/etc";
     static String keyStoreFile = "keystore";
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";

From 8a385b110f80aa889949c1c41bb06773f171e272 Mon Sep 17 00:00:00 2001
From: Mattias Tobiasson 
Date: Tue, 4 Mar 2014 09:35:54 +0100
Subject: [PATCH 248/265] 8031065:
 java/lang/management/MemoryMXBean/LowMemoryTest2.sh fails: OutOfMemoryError:
 Metaspace

Load classes until getUsageThresholdCount() > 0 instead of isUsageThresholdExceeded().

Reviewed-by: dfuchs, sjiang, sla
---
 .../MemoryMXBean/LowMemoryTest2.java          | 66 ++++++++-----------
 1 file changed, 26 insertions(+), 40 deletions(-)

diff --git a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
index cde81675c39..638b053f086 100644
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
@@ -67,7 +67,7 @@ public class LowMemoryTest2 {
 
         static int count = 100000;
 
-        Class loadNext() throws ClassNotFoundException {
+        Class loadNext() {
 
             // public class TestNNNNNN extends java.lang.Object{
             // public TestNNNNNN();
@@ -135,63 +135,49 @@ public class LowMemoryTest2 {
         }
 
         /*
-         * Run method for thread that continuously loads classes.
-         *
-         * Note: Once the usage threshold has been exceeded the low memory
-         * detector thread will attempt to deliver its notification - this can
-         * potentially create a race condition with this thread contining to
-         * fill up metaspace. To avoid the low memory detector getting an
-         * OutOfMemory we throttle this thread once the threshold has been
-         * exceeded.
+         * Load classes until MemoryPoolMXBean.getUsageThresholdCount() > 0.
+         * Then wait for the memory threshold notification to be received.
          */
         public void run() {
-            List pools = ManagementFactory.getMemoryPoolMXBeans();
+            List pools = ManagementFactory.getMemoryPoolMXBeans();
             boolean thresholdExceeded = false;
 
-            for (;;) {
-                try {
-                    // the classes are small so we load 10 at a time
-                    for (int i=0; i<10; i++) {
-                        loadNext();
-                    }
-                } catch (ClassNotFoundException x) {
-                    return;
-                }
-                if (listenerInvoked) {
-                    return;
+            // Load classes until MemoryPoolMXBean.getUsageThresholdCount() > 0
+            while (!thresholdExceeded) {
+                // the classes are small so we load 10 at a time
+                for (int i=0; i<10; i++) {
+                    loadNext();
                 }
 
-                // if threshold has been exceeded we put in a delay to allow
-                // the low memory detector do its job.
-                if (thresholdExceeded) {
-                    try {
-                        Thread.currentThread().sleep(100);
-                    } catch (InterruptedException x) { }
-                } else {
-                    // check if the threshold has been exceeded
-                    ListIterator i = pools.listIterator();
-                    while (i.hasNext()) {
-                        MemoryPoolMXBean p = (MemoryPoolMXBean) i.next();
-                        if (p.getType() == MemoryType.NON_HEAP &&
-                            p.isUsageThresholdSupported())
-                        {
-                            thresholdExceeded = p.isUsageThresholdExceeded();
-                        }
+                // check if the threshold has been exceeded
+                for (MemoryPoolMXBean p : pools) {
+                    if (p.getType() == MemoryType.NON_HEAP &&
+                        p.isUsageThresholdSupported() &&
+                        p.getUsageThresholdCount() > 0)
+                    {
+                        thresholdExceeded = true;
+                        break;
                     }
                 }
             }
+
+            System.out.println("thresholdExceeded. Waiting for notification");
+            while (!listenerInvoked) {
+                try {
+                    Thread.currentThread().sleep(10);
+                } catch (InterruptedException x) {}
+            }
         }
     }
 
     public static void main(String args[]) {
-        ListIterator iter = ManagementFactory.getMemoryPoolMXBeans().listIterator();
+        List pools = ManagementFactory.getMemoryPoolMXBeans();
 
         // Set threshold of 80% of all NON_HEAP memory pools
         // In the Hotspot implementation this means we should get a notification
         // if the CodeCache or metaspace fills up.
 
-        while (iter.hasNext()) {
-            MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
+        for (MemoryPoolMXBean p : pools) {
             if (p.getType() == MemoryType.NON_HEAP && p.isUsageThresholdSupported()) {
 
                 // set threshold

From cad7f300a2d9782c2503051691d6ec125db90ce9 Mon Sep 17 00:00:00 2001
From: Erik Joelsson 
Date: Tue, 4 Mar 2014 10:22:25 +0100
Subject: [PATCH 249/265] 8036145: Solaris standard grep does not understand
 -qE

Reviewed-by: alanb, tbell
---
 common/autoconf/configure | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/autoconf/configure b/common/autoconf/configure
index 730f51a0c0f..636f6e8efdd 100644
--- a/common/autoconf/configure
+++ b/common/autoconf/configure
@@ -127,11 +127,11 @@ function shell_quote() {
   if [[ -n "$1" ]]; then
     # Uses only shell-safe characters?  No quoting needed.
     # '=' is a zsh meta-character, but only in word-initial position.
-    if echo "$1" | grep -qE '^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.:,%/+=_-]+$' \
-        && ! echo "$1" | grep -qE '^='; then
+    if echo "$1" | grep '^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\.:,%/+=_-]\{1,\}$' > /dev/null \
+        && ! echo "$1" | grep '^=' > /dev/null; then
       quoted="$1"
     else
-      if echo "$1" | grep -qE "[\'!]"; then
+      if echo "$1" | grep "[\'!]" > /dev/null; then
         # csh does history expansion within single quotes, but not
         # when backslash-escaped!
         local quoted_quote="'\\''" quoted_exclam="'\\!'"

From 0e750a1a19c06c6d650178d699bf93939ec75526 Mon Sep 17 00:00:00 2001
From: Erik Joelsson 
Date: Wed, 5 Mar 2014 10:21:38 +0100
Subject: [PATCH 250/265] 8019729: JDK build HIGHEST compiler optimisation
 setting isn't valid for Sun C++ compiler

Reviewed-by: tbell
---
 common/autoconf/flags.m4               | 6 +++---
 common/autoconf/generated-configure.sh | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index 5a13e8146d9..613afc319a1 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -272,11 +272,11 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION],
 
   # Optimization levels
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
-    CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xalias_level=basic -xbuiltin=%all -xdepend -xrestrict -xlibmil"
+    CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil"
 
     if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then
       # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global?
-      C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xregs=no%frameptr"
+      C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr"
       C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr"
       C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr"
       C_O_FLAG_NONE="-xregs=no%frameptr"
@@ -289,7 +289,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION],
         CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium"
       fi
     elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then
-      C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra"
+      C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra"
       C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0"
       C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0"
       C_O_FLAG_NONE=""
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 543fea05b55..7473edb634f 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -4221,7 +4221,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1393867368
+DATE_WHEN_GENERATED=1394011255
 
 ###############################################################################
 #
@@ -41327,11 +41327,11 @@ $as_echo "$ac_cv_c_bigendian" >&6; }
 
   # Optimization levels
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
-    CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xalias_level=basic -xbuiltin=%all -xdepend -xrestrict -xlibmil"
+    CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil"
 
     if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then
       # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global?
-      C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xregs=no%frameptr"
+      C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr"
       C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr"
       C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr"
       C_O_FLAG_NONE="-xregs=no%frameptr"
@@ -41344,7 +41344,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; }
         CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium"
       fi
     elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then
-      C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra"
+      C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra"
       C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0"
       C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0"
       C_O_FLAG_NONE=""

From ee1b7412a0f509caaa6e3d18c9cfc5a10f825485 Mon Sep 17 00:00:00 2001
From: Frederic Parain 
Date: Wed, 5 Mar 2014 10:52:33 +0000
Subject: [PATCH 251/265] 8035952: Remove use of JVM_Open, JVM_Read and
 JVM_Close functions from serviceability code

Reviewed-by: chegar, mchung, alanb, sla
---
 .../sun/management/OperatingSystemImpl.c      | 21 +++++++++++--------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c b/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c
index 898a0f9e58a..00c4d558c96 100644
--- a/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c
+++ b/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -196,7 +196,7 @@ Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0
     char* addr;
     int fd;
 
-    fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
+    fd = open64("/proc/self/psinfo", O_RDONLY, 0);
     if (fd < 0) {
         throw_internal_error(env, "Unable to open /proc/self/psinfo");
         return -1;
@@ -204,17 +204,20 @@ Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0
 
     addr = (char *)&psinfo;
     for (remaining = sizeof(psinfo_t); remaining > 0;) {
-        result = JVM_Read(fd, addr, remaining);
+        result = read(fd, addr, remaining);
         if (result < 0) {
-            JVM_Close(fd);
-            throw_internal_error(env, "Unable to read /proc/self/psinfo");
-            return -1;
+            if (errno != EINTR) {
+                close(fd);
+                throw_internal_error(env, "Unable to read /proc/self/psinfo");
+                return -1;
+            }
+        } else {
+            remaining -= result;
+            addr += result;
         }
-        remaining -= result;
-        addr += result;
     }
 
-    JVM_Close(fd);
+    close(fd);
     return (jlong) psinfo.pr_size * 1024;
 #elif defined(__linux__)
     FILE *fp;

From 9b7198c0bb7e85cea62d5d75b262e5f6bd859267 Mon Sep 17 00:00:00 2001
From: Xue-Lei Andrew Fan 
Date: Wed, 5 Mar 2014 13:28:37 +0000
Subject: [PATCH 252/265] 8036676: Rename class name testEnabledProtocols to
 TestEnabledProtocols

Reviewed-by: weijun
---
 ...dProtocols.java => TestEnabledProtocols.java} | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
 rename jdk/test/javax/net/ssl/SSLSession/{testEnabledProtocols.java => TestEnabledProtocols.java} (97%)

diff --git a/jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java b/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java
similarity index 97%
rename from jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java
rename to jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java
index 0e6e8b197c8..c09794c3112 100644
--- a/jdk/test/javax/net/ssl/SSLSession/testEnabledProtocols.java
+++ b/jdk/test/javax/net/ssl/SSLSession/TestEnabledProtocols.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,6 +21,9 @@
  * questions.
  */
 
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
 /*
  * @test
  * @bug 4416068 4478803 4479736
@@ -30,10 +33,7 @@
  *                  session
  *          4701722 protocol mismatch exceptions should be consistent between
  *                  SSLv3 and TLSv1
- * @run main/othervm testEnabledProtocols
- *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
+ * @run main/othervm TestEnabledProtocols
  * @author Ram Marti
  */
 
@@ -44,7 +44,7 @@ import java.security.*;
 import javax.net.ssl.*;
 import java.security.cert.*;
 
-public class testEnabledProtocols {
+public class TestEnabledProtocols {
 
     /*
      * For each of the valid protocols combinations, start a server thread
@@ -135,10 +135,10 @@ public class testEnabledProtocols {
         if (debug)
             System.setProperty("javax.net.debug", "all");
 
-        new testEnabledProtocols();
+        new TestEnabledProtocols();
     }
 
-    testEnabledProtocols() throws Exception  {
+    TestEnabledProtocols() throws Exception  {
         /*
          * Start the tests.
          */

From 61da35fe43963df6a7135494e186c71c83792164 Mon Sep 17 00:00:00 2001
From: Staffan Larsen 
Date: Wed, 5 Mar 2014 15:43:18 +0100
Subject: [PATCH 253/265] 8036675: Compiler warnings in serviceability code

Reviewed-by: alanb, mgronlun
---
 jdk/src/share/demo/jvmti/hprof/hprof_init.c   | 6 +++---
 jdk/src/share/native/sun/tracing/dtrace/JVM.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_init.c b/jdk/src/share/demo/jvmti/hprof/hprof_init.c
index ba79f504a0e..a05527861f1 100644
--- a/jdk/src/share/demo/jvmti/hprof/hprof_init.c
+++ b/jdk/src/share/demo/jvmti/hprof/hprof_init.c
@@ -237,7 +237,7 @@ list_all_tables(void)
  * such a connection can't be made.
  */
 static int
-connect_to_socket(char *hostname, unsigned short port)
+connect_to_socket(char *hostname, int port)
 {
     int fd;
 
@@ -251,7 +251,7 @@ connect_to_socket(char *hostname, unsigned short port)
     }
 
     /* create a socket */
-    fd = md_connect(hostname, port);
+    fd = md_connect(hostname, (unsigned short)port);
     return fd;
 }
 
@@ -817,7 +817,7 @@ parse_options(char *command_line_options)
 
     if ( gdata->net_port > 0 ) {
         LOG2("Agent_OnLoad", "Connecting to socket");
-        gdata->fd = connect_to_socket(gdata->net_hostname, (unsigned short)gdata->net_port);
+        gdata->fd = connect_to_socket(gdata->net_hostname, gdata->net_port);
         if (gdata->fd <= 0) {
             char errmsg[120];
 
diff --git a/jdk/src/share/native/sun/tracing/dtrace/JVM.c b/jdk/src/share/native/sun/tracing/dtrace/JVM.c
index d17f8a87e1a..85cf155f375 100644
--- a/jdk/src/share/native/sun/tracing/dtrace/JVM.c
+++ b/jdk/src/share/native/sun/tracing/dtrace/JVM.c
@@ -287,9 +287,9 @@ Java_sun_tracing_dtrace_JVM_defineClass0(
 
     if (name != NULL) {
         int i;
-        int len = (*env)->GetStringUTFLength(env, name);
+        jsize len = (*env)->GetStringUTFLength(env, name);
         int unicode_len = (*env)->GetStringLength(env, name);
-        if (len >= sizeof(buf)) {
+        if (len >= (jsize)sizeof(buf)) {
             utfName = malloc(len + 1);
             if (utfName == NULL) {
                 goto free_body;

From 70af1402f4761fa0b8783df1ea6d90c2785d7371 Mon Sep 17 00:00:00 2001
From: Staffan Larsen 
Date: Wed, 5 Mar 2014 16:55:38 +0100
Subject: [PATCH 254/265] 8036132: Tab characters in test/com/sun/jdi files

Reviewed-by: alanb, mikael
---
 jdk/test/com/sun/jdi/CatchPatternTest.sh      | 54 +++++++++----------
 .../com/sun/jdi/GetLocalVariables4Test.sh     | 12 ++---
 jdk/test/com/sun/jdi/JdbReadTwiceTest.sh      |  2 +-
 jdk/test/com/sun/jdi/NullLocalVariable.sh     | 10 ++--
 jdk/test/com/sun/jdi/PrivateTransportTest.sh  |  4 +-
 jdk/test/com/sun/jdi/RedefineFinal.sh         | 12 ++---
 .../com/sun/jdi/RedefineIntConstantToLong.sh  | 10 ++--
 jdk/test/com/sun/jdi/StringConvertTest.sh     |  2 +-
 jdk/test/com/sun/jdi/SuspendNoFlagTest.sh     |  4 +-
 9 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/jdk/test/com/sun/jdi/CatchPatternTest.sh b/jdk/test/com/sun/jdi/CatchPatternTest.sh
index b467d5c1e52..a490760db4e 100644
--- a/jdk/test/com/sun/jdi/CatchPatternTest.sh
+++ b/jdk/test/com/sun/jdi/CatchPatternTest.sh
@@ -35,44 +35,44 @@ createJavaFile()
     cat < $classname.java.1
 public class $classname {
     public void bark(int i) {
-	System.out.println(" bark: " + i);
-	switch (i) {
-	case 0:
-	    throw new IllegalArgumentException("IllegalArgumentException");
-	case 1:
-	    throw new ArithmeticException("ArithmeticException");
-	case 2:
-	    throw new IllegalMonitorStateException("IllegalMonitorStateException");
-	case 3:
-	    throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
-	default:
-	    throw new Error("should not happen");
-	}
+        System.out.println(" bark: " + i);
+        switch (i) {
+        case 0:
+            throw new IllegalArgumentException("IllegalArgumentException");
+        case 1:
+            throw new ArithmeticException("ArithmeticException");
+        case 2:
+            throw new IllegalMonitorStateException("IllegalMonitorStateException");
+        case 3:
+            throw new IndexOutOfBoundsException("IndexOutOfBoundsException");
+        default:
+            throw new Error("should not happen");
+        }
     }
     public void loop(int max) {
-	for (int i = 0; i <= max; i++) {
-	    try {
-		bark(i);
-	    } catch(RuntimeException re) {
-		System.out.println(" loop: " + re.getMessage() +
-				   " caught and ignored.");
-	    }
-	}
+        for (int i = 0; i <= max; i++) {
+            try {
+                bark(i);
+            } catch(RuntimeException re) {
+                System.out.println(" loop: " + re.getMessage() +
+                       " caught and ignored.");
+            }
+        }
     }
     public void partOne() {
         loop(2);
-	System.out.println("partOne completed");
+        System.out.println("partOne completed");
     }
     public void partTwo() {
         loop(3);
-	System.out.println("partTwo completed");
+        System.out.println("partTwo completed");
     }
     public static void main(String[] args) {
-	System.out.println("Howdy!");
+        System.out.println("Howdy!");
         $classname my = new $classname();
-	my.partOne();
-	my.partTwo();
-	System.out.println("Goodbye from $classname!");
+        my.partOne();
+        my.partTwo();
+        System.out.println("Goodbye from $classname!");
     }
 }
 EOF
diff --git a/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh b/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh
index 9af3409b96b..bba2d90a86a 100644
--- a/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh
+++ b/jdk/test/com/sun/jdi/GetLocalVariables4Test.sh
@@ -39,12 +39,12 @@ createJavaFile()
 public class GetLocalVariables4Targ {
     public static void main(String[] args) {
         System.out.println("Howdy!");
-	int i = 0;
-	try {
-	    i = 16 / i;
-	} catch(Exception e) {
-	    System.out.println("e should be visible");    // @1 breakpoint
-	}
+        int i = 0;
+        try {
+            i = 16 / i;
+        } catch(Exception e) {
+            System.out.println("e should be visible");    // @1 breakpoint
+        }
         System.out.println("Goodbye from GetLocalVariables4Targ!");
     }
 }
diff --git a/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh b/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh
index 6f3cb193743..b7ca50de096 100644
--- a/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh
+++ b/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh
@@ -219,7 +219,7 @@ if [ ! -r c:/ ] ; then
       echo "Unable to make file unreadable, so test will fail. chmod: $HOME/jdb.ini"
       if grep -q "uid=0" $HOME/jdb.ini  ; then
         echo "The test is running as root. Fix infrastructure!"
-      fi	
+      fi
     fi  
     doit
     failIfNot 1 "open: $HOME/jdb.ini"
diff --git a/jdk/test/com/sun/jdi/NullLocalVariable.sh b/jdk/test/com/sun/jdi/NullLocalVariable.sh
index 63c0c4aac38..ce38929471f 100644
--- a/jdk/test/com/sun/jdi/NullLocalVariable.sh
+++ b/jdk/test/com/sun/jdi/NullLocalVariable.sh
@@ -54,11 +54,11 @@ EOF
 dojdbCmds()
 {
    #set -x
-   cmd stop at badscope:4	; $sleepcmd
-   runToBkpt			; $sleepcmd
-   cmd next			; $sleepcmd
-   cmd next			; $sleepcmd
-   cmd locals			; $sleepcmd
+   cmd stop at badscope:4   ; $sleepcmd
+   runToBkpt                ; $sleepcmd
+   cmd next                 ; $sleepcmd
+   cmd next                 ; $sleepcmd
+   cmd locals               ; $sleepcmd
    cmd allowExit cont
 }
 
diff --git a/jdk/test/com/sun/jdi/PrivateTransportTest.sh b/jdk/test/com/sun/jdi/PrivateTransportTest.sh
index ee8051f46ee..7f4b0029f26 100644
--- a/jdk/test/com/sun/jdi/PrivateTransportTest.sh
+++ b/jdk/test/com/sun/jdi/PrivateTransportTest.sh
@@ -67,9 +67,9 @@ if [ -z "${TESTJAVA}" ] ; then
    # is given on the command line, tell the user that and use a default.
    # THIS IS THE JDK BEING TESTED.
    if [ -n "$1" ] ; then
-          TESTJAVA=$1
+         TESTJAVA=$1
       else
-	  TESTJAVA=$JAVA_HOME
+         TESTJAVA=$JAVA_HOME
    fi
    TESTSRC=.
    TESTCLASSES=.
diff --git a/jdk/test/com/sun/jdi/RedefineFinal.sh b/jdk/test/com/sun/jdi/RedefineFinal.sh
index 16381381b14..c35a29d7019 100644
--- a/jdk/test/com/sun/jdi/RedefineFinal.sh
+++ b/jdk/test/com/sun/jdi/RedefineFinal.sh
@@ -42,15 +42,15 @@ createJavaFile()
 public final class $1 {
 
     public int m1(int i) {
-	// @1 uncomment System.out.println("I'm here");
-	return m2(i, 1000);
+        // @1 uncomment System.out.println("I'm here");
+        return m2(i, 1000);
     }
 
     public int m2(int i, int j) {
-	if (i < 0 || j < 0) {	// @1 breakpoint
+        if (i < 0 || j < 0) {   // @1 breakpoint
             throw new IllegalArgumentException();
-	}
-	return i+j;
+        }
+        return i+j;
     }
 
     $1() {
@@ -59,7 +59,7 @@ public final class $1 {
     }
 
     public static void main(String args[]) {
-	new $1();
+        new $1();
     }
 }
 EOF
diff --git a/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh b/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh
index 4f384dff504..112c6c3e53d 100644
--- a/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh
+++ b/jdk/test/com/sun/jdi/RedefineIntConstantToLong.sh
@@ -44,18 +44,18 @@ public final class $1 {
     public long m1(int i) {
         long r=0;
         r = m2(i * 2); // @1 commentout
-	// @1 uncomment      r =m2(i * 2L);
+        // @1 uncomment      r =m2(i * 2L);
         return r;
     }
 
     public long m2(int j) {
-	System.out.println(System.getProperty("line.separator") + 
+        System.out.println(System.getProperty("line.separator") + 
                            "**** public long m2(int j) with value: " + j);
         return j;
     }
 
     public long m2(long j) {
-	System.out.println(System.getProperty("line.separator") + 
+        System.out.println(System.getProperty("line.separator") + 
                            "**** public long m2(long j) with value: " + j);
         return j;
     }
@@ -66,7 +66,7 @@ public final class $1 {
         r1 = m1(1000);
         r2 = 0;         // @1 breakpoint
         r2 = m1(1000);
-        if (r1 != r2) {	// @1 breakpoint
+        if (r1 != r2) { // @1 breakpoint
              throw new Exception("FAILURE: Expected value: " + r1 + " Actual value: " + r2);
         } else {
              System.out.println("SUCCESS: Expected value: " + r1 + " Actual value: " + r2);
@@ -74,7 +74,7 @@ public final class $1 {
     }
 
     public static void main(String args[]) throws Exception {
-	new $1().doit();
+        new $1().doit();
     }
 }
 EOF
diff --git a/jdk/test/com/sun/jdi/StringConvertTest.sh b/jdk/test/com/sun/jdi/StringConvertTest.sh
index 181105c6257..053396c9297 100644
--- a/jdk/test/com/sun/jdi/StringConvertTest.sh
+++ b/jdk/test/com/sun/jdi/StringConvertTest.sh
@@ -23,7 +23,7 @@
 # questions.
 #
 
-#  @test @(#)StringConvertTest.sh	1.6 03/04/09
+#  @test
 #  @bug 4511950 4843082
 #  @summary 1. jdb's expression evaluation doesn't perform string conversion properly
 #           2. TTY: run on expression evaluation
diff --git a/jdk/test/com/sun/jdi/SuspendNoFlagTest.sh b/jdk/test/com/sun/jdi/SuspendNoFlagTest.sh
index 7608cb574c9..dd4a24e4d76 100644
--- a/jdk/test/com/sun/jdi/SuspendNoFlagTest.sh
+++ b/jdk/test/com/sun/jdi/SuspendNoFlagTest.sh
@@ -68,9 +68,9 @@ if [ -z "${TESTJAVA}" ] ; then
    # is given on the command line, tell the user that and use a default.
    # THIS IS THE JDK BEING TESTED.
    if [ -n "$1" ] ; then
-          TESTJAVA=$1
+         TESTJAVA=$1
       else
-	  TESTJAVA=$JAVA_HOME
+         TESTJAVA=$JAVA_HOME
    fi
    TESTSRC=.
    TESTCLASSES=.

From 5a678f7c26a87a53fb6adefa194d3884f301b807 Mon Sep 17 00:00:00 2001
From: Staffan Larsen 
Date: Wed, 5 Mar 2014 20:03:32 +0100
Subject: [PATCH 255/265] 8036599: Use Diagnostic Commands instead of SA by
 default in jinfo

Reviewed-by: alanb
---
 .../share/classes/sun/tools/jinfo/JInfo.java  | 148 ++++++++++++------
 jdk/test/sun/tools/jinfo/Basic.sh             |  26 ++-
 2 files changed, 123 insertions(+), 51 deletions(-)

diff --git a/jdk/src/share/classes/sun/tools/jinfo/JInfo.java b/jdk/src/share/classes/sun/tools/jinfo/JInfo.java
index d5adc35379a..0c1d6a1e677 100644
--- a/jdk/src/share/classes/sun/tools/jinfo/JInfo.java
+++ b/jdk/src/share/classes/sun/tools/jinfo/JInfo.java
@@ -26,18 +26,18 @@
 package sun.tools.jinfo;
 
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.io.IOException;
 import java.io.InputStream;
 
 import com.sun.tools.attach.VirtualMachine;
+
 import sun.tools.attach.HotSpotVirtualMachine;
 
 /*
  * This class is the main class for the JInfo utility. It parses its arguments
  * and decides if the command should be satisfied using the VM attach mechanism
- * or an SA tool. At this time the only option that uses the VM attach
- * mechanism is the -flag option to set or print a command line option of a
- * running application. All other options are mapped to SA tools.
+ * or an SA tool.
  */
 public class JInfo {
 
@@ -46,62 +46,95 @@ public class JInfo {
             usage(1); // no arguments
         }
 
-        boolean useSA = true;
-        String arg1 = args[0];
-        if (arg1.startsWith("-")) {
-            if (arg1.equals("-flags") ||
-                arg1.equals("-sysprops")) {
-                // SA JInfo needs  or  or
-                // ( and ). So, total
-                // argument count including option has to 2 or 3.
-                if (args.length != 2 && args.length != 3) {
-                    usage(1);
+        // First determine if we should launch SA or not
+        boolean useSA = false;
+        if (args[0].equals("-F")) {
+            // delete the -F
+            args = Arrays.copyOfRange(args, 1, args.length);
+            useSA = true;
+        } else if (args[0].equals("-flags")
+            || args[0].equals("-sysprops"))
+        {
+            if (args.length == 2) {
+                if (!args[1].matches("[0-9]+")) {
+                    // If args[1] doesn't parse to a number then
+                    // it must be the SA debug server
+                    // (otherwise it is the pid)
+                    useSA = true;
                 }
-            } else if (arg1.equals("-flag")) {
-                // do not use SA, use attach-on-demand
-                useSA = false;
-            } else {
-                // unknown option or -h or -help, print help
-                int exit;
-                if (arg1.equals("-help") || arg1.equals("-h")) {
-                    exit = 0;
-                } else {
-                    exit = 1;
-                }
-                usage(exit);
             }
+            if (args.length == 3) {
+                // arguments include an executable and a core file
+                useSA = true;
+            }
+        } else if (!args[0].startsWith("-")) {
+            if (args.length == 2) {
+                // the only arguments are an executable and a core file
+                useSA = true;
+            }
+        } else if (args[0].equals("-h")
+                || args[0].equals("-help")) {
+            usage(0);
         }
 
         if (useSA) {
+            // invoke SA which does it's own argument parsing
             runTool(args);
         } else {
-            if (args.length == 3) {
-                String pid = args[2];
-                String option = args[1];
-                flag(pid, option);
-            } else {
-                int exit;
-                if (arg1.equals("-help") || arg1.equals("-h")) {
-                    exit = 0;
-                } else {
-                    exit = 1;
+            // Now we can parse arguments for the non-SA case
+            String pid = null;
+
+            switch(args[0]) {
+            case "-flag":
+                if (args.length != 3) {
+                    usage(1);
                 }
-                usage(exit);
+                String option = args[1];
+                pid = args[2];
+                flag(pid, option);
+                break;
+            case "-flags":
+                if (args.length != 2) {
+                    usage(1);
+                }
+                pid = args[1];
+                flags(pid);
+                break;
+            case "-sysprops":
+                if (args.length != 2) {
+                    usage(1);
+                }
+                pid = args[1];
+                sysprops(pid);
+                break;
+            case "-help":
+            case "-h":
+                usage(0);
+            default:
+               if (args.length == 1) {
+                   // no flags specified, we do -sysprops and -flags
+                   pid = args[0];
+                   sysprops(pid);
+                   System.out.println();
+                   flags(pid);
+               } else {
+                   usage(1);
+               }
             }
         }
     }
 
-    // Invoke SA tool  with the given arguments
+    // Invoke SA tool with the given arguments
     private static void runTool(String args[]) throws Exception {
         String tool = "sun.jvm.hotspot.tools.JInfo";
-        // Tool not available on this  platform.
+        // Tool not available on this platform.
         Class c = loadClass(tool);
         if (c == null) {
             usage(1);
         }
 
         // invoke the main method with the arguments
-        Class[] argTypes = { String[].class } ;
+        Class[] argTypes = { String[].class } ;
         Method m = c.getDeclaredMethod("main", argTypes);
 
         Object[] invokeArgs = { args };
@@ -111,7 +144,7 @@ public class JInfo {
     // loads the given class using the system class loader
     private static Class loadClass(String name) {
         //
-        // We specify the system clas loader so as to cater for development
+        // We specify the system class loader so as to cater for development
         // environments where this class is on the boot class path but sa-jdi.jar
         // is on the system class path. Once the JDK is deployed then both
         // tools.jar and sa-jdi.jar are on the system class path.
@@ -124,28 +157,28 @@ public class JInfo {
     }
 
     private static void flag(String pid, String option) throws IOException {
-        VirtualMachine vm = attach(pid);
+        HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
         String flag;
         InputStream in;
         int index = option.indexOf('=');
         if (index != -1) {
             flag = option.substring(0, index);
             String value = option.substring(index + 1);
-            in = ((HotSpotVirtualMachine)vm).setFlag(flag, value);
+            in = vm.setFlag(flag, value);
         } else {
             char c = option.charAt(0);
             switch (c) {
                 case '+':
                     flag = option.substring(1);
-                    in = ((HotSpotVirtualMachine)vm).setFlag(flag, "1");
+                    in = vm.setFlag(flag, "1");
                     break;
                 case '-':
                     flag = option.substring(1);
-                    in = ((HotSpotVirtualMachine)vm).setFlag(flag, "0");
+                    in = vm.setFlag(flag, "0");
                     break;
                 default:
                     flag = option;
-                    in = ((HotSpotVirtualMachine)vm).printFlag(flag);
+                    in = vm.printFlag(flag);
                     break;
             }
         }
@@ -153,6 +186,20 @@ public class JInfo {
         drain(vm, in);
     }
 
+    private static void flags(String pid) throws IOException {
+        HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
+        InputStream in = vm.executeJCmd("VM.flags");
+        System.out.println("VM Flags:");
+        drain(vm, in);
+    }
+
+    private static void sysprops(String pid) throws IOException {
+        HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid);
+        InputStream in = vm.executeJCmd("VM.system_properties");
+        System.out.println("Java System Properties:");
+        drain(vm, in);
+    }
+
     // Attach to , exiting if we fail to attach
     private static VirtualMachine attach(String pid) {
         try {
@@ -195,7 +242,9 @@ public class JInfo {
         System.err.println("Usage:");
         if (usageSA) {
             System.err.println("    jinfo [option] ");
-            System.err.println("        (to connect to running process)");
+            System.err.println("        (to connect to a running process)");
+            System.err.println("    jinfo -F [option] ");
+            System.err.println("        (to connect to a hung process)");
             System.err.println("    jinfo [option]  ");
             System.err.println("        (to connect to a core file)");
             System.err.println("    jinfo [option] [server_id@]");
@@ -206,10 +255,10 @@ public class JInfo {
             System.err.println("    -flag          to print the value of the named VM flag");
             System.err.println("    -flag [+|-]    to enable or disable the named VM flag");
             System.err.println("    -flag = to set the named VM flag to the given value");
-            System.err.println("  for running processes and core files:");
+            System.err.println("  for running or hung processes and core files:");
             System.err.println("    -flags               to print VM flags");
             System.err.println("    -sysprops            to print Java system properties");
-            System.err.println("              to print both of the above");
+            System.err.println("              to print both VM flags and system properties");
             System.err.println("    -h | -help           to print this help message");
         } else {
             System.err.println("    jinfo