Mercurial > hg > release > icedtea7-forest-2.5 > hotspot
changeset 5793:f7e4613bba96
Merge
author | asaha |
---|---|
date | Thu, 02 Oct 2014 08:23:19 -0700 |
parents | 6183327bf9c1 (current diff) a6ae698522bf (diff) |
children | af55a74be9b6 |
files | .hgtags |
diffstat | 37 files changed, 479 insertions(+), 176 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Sep 11 10:59:36 2014 -0700 +++ b/.hgtags Thu Oct 02 08:23:19 2014 -0700 @@ -724,3 +724,18 @@ d6cb97651f0bd8d61f4d22aa7550145bbe6fb051 jdk7u71-b11 959b4e5d2e3111920c198187f3bc66eba3e457f1 jdk7u71-b12 608f470d22689bab17bab0ea1dbee3e1a0802d5b jdk7u71-b13 +ad909197a1ce2df483a20ff9ac380382f779a9d3 jdk7u71-b14 +1bd3adac3aac3c29c81303812b35f484ff90cb2b jdk7u72-b01 +0caed46767e35c00eff69b22acf984d98eb66b3d jdk7u72-b02 +3a2934191de4bb8ca9d2faca93f3381e521e8cac jdk7u72-b03 +e4708cde2898df4c936595aacb57bc5b4e15869a jdk7u72-b04 +137e0859cd296cb8d9f9e327112ddc793ed59318 jdk7u72-b05 +4d9d227d70f33b70461230172386217317954312 jdk7u72-b06 +ece56f93f37b41b9c8875e54fbd8010277f6b460 jdk7u72-b07 +439c695a7aa03652ab92681120434b9ce8cdd2b7 jdk7u72-b08 +a27f16d45457a68a723acca621cb11bc173a0eb6 jdk7u72-b09 +e6508ab77271d1d3ce7b5f60d91a7334fdacb03a jdk7u72-b10 +c17a8487086433e14cd22373039a8b6b48e7cbb8 jdk7u72-b11 +a9e695f0d831f115720a4dcad3d33e0003b0acad jdk7u72-b12 +ac701f87d1ea46033c69f3e1cb84fc0a971da70c jdk7u72-b13 +d9b56c6bdddb6f9d8242230f5fdd58f9c7d30ea5 jdk7u72-b14
--- a/agent/src/os/linux/libproc.h Thu Sep 11 10:59:36 2014 -0700 +++ b/agent/src/os/linux/libproc.h Thu Oct 02 08:23:19 2014 -0700 @@ -34,19 +34,7 @@ #include "libproc_md.h" #endif -#if defined(sparc) || defined(sparcv9) -/* - If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64 - otherwise it should be from /usr/include/asm-sparc - These two files define pt_regs structure differently -*/ -#ifdef _LP64 -#include "asm-sparc64/ptrace.h" -#else -#include "asm-sparc/ptrace.h" -#endif - -#endif //sparc or sparcv9 +#include <linux/ptrace.h> /************************************************************************************
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Thu Sep 11 10:59:36 2014 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, 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 @@ -61,8 +61,9 @@ long h = 0; int s = 0; int len = buf.length; + // Emulate the unsigned int in java_lang_String::hash_code while (len-- > 0) { - h = 31*h + (0xFFL & buf[s]); + h = 31*h + (0xFFFFFFFFL & buf[s]); s++; } return h & 0xFFFFFFFFL;
--- a/make/hotspot_version Thu Sep 11 10:59:36 2014 -0700 +++ b/make/hotspot_version Thu Oct 02 08:23:19 2014 -0700 @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014 HS_MAJOR_VER=24 -HS_MINOR_VER=71 -HS_BUILD_NUMBER=01 +HS_MINOR_VER=72 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/src/cpu/sparc/vm/assembler_sparc.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -1745,7 +1745,7 @@ inline void swap( Register s1, Register s2, Register d ); inline void swap( Register s1, int simm13a, Register d); - inline void swap( Address& a, Register d, int offset = 0 ); + inline void swap( const Address& a, Register d, int offset = 0 ); // pp 232
--- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -347,7 +347,7 @@ inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::swap( Address& a, Register d, int offset ) { +inline void Assembler::swap( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); if (a.has_index()) { assert(offset == 0, ""); swap( a.base(), a.index(), d ); } else { swap( a.base(), a.disp() + offset, d ); }
--- a/src/cpu/sparc/vm/copy_sparc.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/copy_sparc.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -184,7 +184,7 @@ assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); if (value == 0 && UseBlockZeroing && - (count > (BlockZeroingLowLimit >> LogHeapWordSize))) { + (count > (size_t)(BlockZeroingLowLimit >> LogHeapWordSize))) { // Call it only when block zeroing is used ((_zero_Fn)StubRoutines::zero_aligned_words())(tohw, count); } else {
--- a/src/cpu/sparc/vm/frame_sparc.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/frame_sparc.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -282,8 +282,8 @@ // next two fns read and write Lmonitors value, private: - BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } - void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } + BasicObjectLock* interpreter_frame_monitors() const; + void interpreter_frame_set_monitors(BasicObjectLock* monitors); #else public: inline interpreterState get_interpreterState() const {
--- a/src/cpu/sparc/vm/frame_sparc.inline.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -217,6 +217,13 @@ return (methodOop*)sp_addr_at( Lmethod->sp_offset_in_saved_window()); } +inline BasicObjectLock* frame::interpreter_frame_monitors() const { + return *interpreter_frame_monitors_addr(); +} + +inline void frame::interpreter_frame_set_monitors(BasicObjectLock* monitors) { + *interpreter_frame_monitors_addr() = monitors; +} // Constant pool cache
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -89,7 +89,7 @@ private: #ifdef PRODUCT -#define inc_counter_np(a,b,c) (0) +#define inc_counter_np(a,b,c) #else #define inc_counter_np(counter, t1, t2) \ BLOCK_COMMENT("inc_counter " #counter); \ @@ -1126,7 +1126,7 @@ Label& L_loop, bool use_prefetch, bool use_bis); void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size, - int iter_size, CopyLoopFunc copy_loop_func) { + int iter_size, StubGenerator::CopyLoopFunc copy_loop_func) { Label L_copy; assert(log2_elem_size <= 3, "the following code should be changed"); @@ -1277,7 +1277,7 @@ __ inc(from, 8); __ sllx(O3, left_shift, O3); - disjoint_copy_core(from, to, count, log2_elem_size, 16, copy_16_bytes_shift_loop); + disjoint_copy_core(from, to, count, log2_elem_size, 16, &StubGenerator::copy_16_bytes_shift_loop); __ inccc(count, count_dec>>1 ); // + 8 bytes __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes); @@ -2156,7 +2156,7 @@ __ dec(count, 4); // The cmp at the beginning guaranty count >= 4 __ sllx(O3, 32, O3); - disjoint_copy_core(from, to, count, 2, 16, copy_16_bytes_loop); + disjoint_copy_core(from, to, count, 2, 16, &StubGenerator::copy_16_bytes_loop); __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes); __ delayed()->inc(count, 4); // restore 'count' @@ -2437,7 +2437,7 @@ // count >= 0 (original count - 8) __ mov(from, from64); - disjoint_copy_core(from64, to64, count, 3, 64, copy_64_bytes_loop); + disjoint_copy_core(from64, to64, count, 3, 64, &StubGenerator::copy_64_bytes_loop); // Restore O4(offset0), O5(offset8) __ sub(from64, from, offset0);
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -48,7 +48,8 @@ sparc64_family = 14, M_family = 15, T_family = 16, - T1_model = 17 + T1_model = 17, + sparc5_instructions = 18 }; enum Feature_Flag_Set { @@ -73,6 +74,7 @@ M_family_m = 1 << M_family, T_family_m = 1 << T_family, T1_model_m = 1 << T1_model, + sparc5_instructions_m = 1 << sparc5_instructions, generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, generic_v9_m = generic_v8_m | v9_instructions_m, @@ -117,6 +119,7 @@ static bool has_vis3() { return (_features & vis3_instructions_m) != 0; } static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; } static bool has_cbcond() { return (_features & cbcond_instructions_m) != 0; } + static bool has_sparc5_instr() { return (_features & sparc5_instructions_m) != 0; } static bool supports_compare_and_exchange() { return has_v9(); } @@ -127,6 +130,7 @@ static bool is_M_series() { return is_M_family(_features); } static bool is_T4() { return is_T_family(_features) && has_cbcond(); } + static bool is_T7() { return is_T_family(_features) && has_sparc5_instr(); } // Fujitsu SPARC64 static bool is_sparc64() { return (_features & sparc64_family_m) != 0; } @@ -146,7 +150,7 @@ static const char* cpu_features() { return _features_str; } static intx prefetch_data_size() { - return is_T4() ? 32 : 64; // default prefetch block size on sparc + return is_T4() && !is_T7() ? 32 : 64; // default prefetch block size on sparc } // Prefetch
--- a/src/os/bsd/vm/os_bsd.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1297,9 +1297,20 @@ ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; }
--- a/src/os/linux/vm/os_linux.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1103,9 +1103,20 @@ ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; }
--- a/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -28,7 +28,7 @@ #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" -#include <asm-sparc/traps.h> +#include <asm/traps.h> void MacroAssembler::read_ccr_trap(Register ccr_save) { // No implementation
--- a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -79,12 +79,12 @@ __asm__ volatile( "1: \n\t" " ldx [%2], %%o2\n\t" - " add %0, %%o2, %%o3\n\t" + " add %1, %%o2, %%o3\n\t" " casx [%2], %%o2, %%o3\n\t" " cmp %%o2, %%o3\n\t" " bne %%xcc, 1b\n\t" " nop\n\t" - " add %0, %%o2, %0\n\t" + " add %1, %%o2, %0\n\t" : "=r" (rv) : "r" (add_value), "r" (dest) : "memory", "o2", "o3");
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -118,7 +118,7 @@ *ret_sp = os::Linux::ucontext_get_sp(uc); } if (ret_fp) { - *ret_fp = os::Linux::ucontext_get_fp(uc); + *ret_fp = (intptr_t*)NULL; } } else { // construct empty ExtendedPC for return value checking @@ -136,18 +136,15 @@ 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, fp, epc.pc()); + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, NULL); + return frame(sp, frame::unpatchable, epc.pc()); } frame os::get_sender_for_C_frame(frame* fr) { - return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); + return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc()); } frame os::current_frame() { - fprintf(stderr, "current_frame()"); - intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); frame myframe(sp, frame::unpatchable, CAST_FROM_FN_PTR(address, os::current_frame)); @@ -302,29 +299,30 @@ if (context == NULL) return; ucontext_t *uc = (ucontext_t*)context; + sigcontext* sc = (sigcontext*)context; intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc); st->print_cr("Register to memory mapping:"); st->cr(); // this is only for the "general purpose" registers - st->print("G1="); print_location(st, SIG_REGS(sc).u_regs[CON__G1]); - st->print("G2="); print_location(st, SIG_REGS(sc).u_regs[CON__G2]); - st->print("G3="); print_location(st, SIG_REGS(sc).u_regs[CON__G3]); - st->print("G4="); print_location(st, SIG_REGS(sc).u_regs[CON__G4]); - st->print("G5="); print_location(st, SIG_REGS(sc).u_regs[CON__G5]); - st->print("G6="); print_location(st, SIG_REGS(sc).u_regs[CON__G6]); - st->print("G7="); print_location(st, SIG_REGS(sc).u_regs[CON__G7]); + st->print("G1="); print_location(st, SIG_REGS(sc).u_regs[CON_G1]); + st->print("G2="); print_location(st, SIG_REGS(sc).u_regs[CON_G2]); + st->print("G3="); print_location(st, SIG_REGS(sc).u_regs[CON_G3]); + st->print("G4="); print_location(st, SIG_REGS(sc).u_regs[CON_G4]); + st->print("G5="); print_location(st, SIG_REGS(sc).u_regs[CON_G5]); + st->print("G6="); print_location(st, SIG_REGS(sc).u_regs[CON_G6]); + st->print("G7="); print_location(st, SIG_REGS(sc).u_regs[CON_G7]); st->cr(); - st->print("O0="); print_location(st, SIG_REGS(sc).u_regs[CON__O0]); - st->print("O1="); print_location(st, SIG_REGS(sc).u_regs[CON__O1]); - st->print("O2="); print_location(st, SIG_REGS(sc).u_regs[CON__O2]); - st->print("O3="); print_location(st, SIG_REGS(sc).u_regs[CON__O3]); - st->print("O4="); print_location(st, SIG_REGS(sc).u_regs[CON__O4]); - st->print("O5="); print_location(st, SIG_REGS(sc).u_regs[CON__O5]); - st->print("O6="); print_location(st, SIG_REGS(sc).u_regs[CON__O6]); - st->print("O7="); print_location(st, SIG_REGS(sc).u_regs[CON__O7]); + st->print("O0="); print_location(st, SIG_REGS(sc).u_regs[CON_O0]); + st->print("O1="); print_location(st, SIG_REGS(sc).u_regs[CON_O1]); + st->print("O2="); print_location(st, SIG_REGS(sc).u_regs[CON_O2]); + st->print("O3="); print_location(st, SIG_REGS(sc).u_regs[CON_O3]); + st->print("O4="); print_location(st, SIG_REGS(sc).u_regs[CON_O4]); + st->print("O5="); print_location(st, SIG_REGS(sc).u_regs[CON_O5]); + st->print("O6="); print_location(st, SIG_REGS(sc).u_regs[CON_O6]); + st->print("O7="); print_location(st, SIG_REGS(sc).u_regs[CON_O7]); st->cr(); st->print("L0="); print_location(st, sp[L0->sp_offset_in_saved_window()]); @@ -525,7 +523,7 @@ if (nativeInstruction_at(*pc)->is_ic_miss_trap()) { #ifdef ASSERT #ifdef TIERED - CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + CodeBlob* cb = CodeCache::find_blob_unsafe(*pc); assert(cb->is_compiled_by_c2(), "Wrong compiler"); #endif // TIERED #endif // ASSERT
--- a/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -55,7 +55,7 @@ if (detect_niagara()) { NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on Niagara");) - features = niagara1_m; + features = niagara1_m | T_family_m; } return features;
--- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -75,13 +75,19 @@ do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); // Extract valid instruction set extensions. - uint_t av; - uint_t avn = os::Solaris::getisax(&av, 1); - assert(avn == 1, "should only return one av"); + uint_t avs[2]; + uint_t avn = os::Solaris::getisax(avs, 2); + assert(avn <= 2, "should return two or less av's"); + uint_t av = avs[0]; #ifndef PRODUCT - if (PrintMiscellaneous && Verbose) - tty->print_cr("getisax(2) returned: " PTR32_FORMAT, av); + if (PrintMiscellaneous && Verbose) { + tty->print("getisax(2) returned: " PTR32_FORMAT, av); + if (avn > 1) { + tty->print(", " PTR32_FORMAT, avs[1]); + } + tty->cr(); + } #endif if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; @@ -91,6 +97,13 @@ if (av & AV_SPARC_POPC) features |= hardware_popc_m; if (av & AV_SPARC_VIS) features |= vis1_instructions_m; if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; + if (avn > 1) { + uint_t av2 = avs[1]; +#ifndef AV2_SPARC_SPARC5 +#define AV2_SPARC_SPARC5 0x00000008 /* The 29 new fp and sub instructions */ +#endif + if (av2 & AV2_SPARC_SPARC5) features |= sparc5_instructions_m; + } // Next values are not defined before Solaris 10 // but Solaris 8 is used for jdk6 update builds.
--- a/src/share/vm/classfile/stackMapTable.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/classfile/stackMapTable.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -70,24 +70,26 @@ bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { int index = get_index_from_offset(target); - return match_stackmap(frame, target, index, match, update, ctx, THREAD); + return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); } // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. +// handler is true if the frame in stackmap_table is for an exception handler. // -// The values of match and update are: _match__update_ +// The values of match and update are: _match__update__handler // -// checking a branch target/exception handler: true false +// checking a branch target: true false false +// checking an exception handler: true false true // linear bytecode verification following an -// unconditional branch: false true +// unconditional branch: false true false // linear bytecode verification not following an -// unconditional branch: true true +// unconditional branch: true true false bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { if (frame_index < 0 || frame_index >= _frame_count) { *ctx = ErrorContext::missing_stackmap(frame->offset()); frame->verifier()->verify_error( @@ -98,11 +100,9 @@ StackMapFrame *stackmap_frame = _frame_array[frame_index]; bool result = true; if (match) { - // when checking handler target, match == true && update == false - bool is_exception_handler = !update; // Has direct control flow from last instruction, need to match the two // frames. - result = frame->is_assignable_to(stackmap_frame, is_exception_handler, + result = frame->is_assignable_to(stackmap_frame, handler, ctx, CHECK_VERIFY_(frame->verifier(), result)); } if (update) { @@ -126,7 +126,7 @@ StackMapFrame* frame, int32_t target, TRAPS) const { ErrorContext ctx; bool match = match_stackmap( - frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); + frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { frame->verifier()->verify_error(ctx, "Inconsistent stackmap frames at branch target %d", target); @@ -134,7 +134,6 @@ } // check if uninitialized objects exist on backward branches check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); - frame->verifier()->update_furthest_jump(target); } void StackMapTable::check_new_object(
--- a/src/share/vm/classfile/stackMapTable.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/classfile/stackMapTable.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, 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 @@ -74,12 +74,12 @@ // specified offset. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Check jump instructions. Make sure there are no uninitialized // instances on backward branch.
--- a/src/share/vm/classfile/verifier.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/classfile/verifier.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -630,8 +630,6 @@ // flow from current instruction to the next // instruction in sequence - set_furthest_jump(0); - Bytecodes::Code opcode; while (!bcs.is_last_bytecode()) { // Check for recursive re-verification before each bytecode. @@ -1788,7 +1786,7 @@ // If matched, current_frame will be updated by this method. bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, - !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); + !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0)); if (!matches) { // report type error verify_error(ctx, "Instruction type does not match stack map"); @@ -1835,7 +1833,7 @@ } ErrorContext ctx; bool matches = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); + new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this)); if (!matches) { verify_error(ctx, "Stack map does not match the one at " "exception handler %d", handler_pc); @@ -2418,13 +2416,6 @@ return; } - // Make sure that this call is not jumped over. - if (bci < furthest_jump()) { - verify_error(ErrorContext::bad_code(bci), - "Bad <init> method call from inside of a branch"); - return; - } - // Check if this call is done from inside of a TRY block. If so, make // sure that all catch clause paths end in a throw. Otherwise, this // can result in returning an incomplete object.
--- a/src/share/vm/classfile/verifier.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/classfile/verifier.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -257,9 +257,6 @@ ErrorContext _error_context; // contains information about an error - // Used to detect illegal jumps over calls to super() and this() in ctors. - int32_t _furthest_jump; - void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); void verify_exception_handler_table(u4 code_length, char* code_data, @@ -413,19 +410,6 @@ TypeOrigin ref_ctx(const char* str, TRAPS); - // Keep track of the furthest branch done in a method to make sure that - // there are no branches over calls to super() or this() from inside of - // a constructor. - int32_t furthest_jump() { return _furthest_jump; } - - void set_furthest_jump(int32_t target) { - _furthest_jump = target; - } - - void update_furthest_jump(int32_t target) { - if (target > _furthest_jump) _furthest_jump = target; - } - }; inline int ClassVerifier::change_sig_to_verificationType(
--- a/src/share/vm/oops/cpCacheOop.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/oops/cpCacheOop.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -140,8 +140,15 @@ oop_store(&_f1, f1); } void release_set_f1(oop f1); - void set_f2(intx f2) { assert(_f2 == 0 || _f2 == f2, "illegal field change"); _f2 = f2; } - void set_f2_as_vfinal_method(methodOop f2) { assert(_f2 == 0 || _f2 == (intptr_t) f2, "illegal field change"); assert(is_vfinal(), "flags must be set"); _f2 = (intptr_t) f2; } + void set_f2(intx f2) { + intx existing_f2 = _f2; // read once + assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change"); + _f2 = f2; + } + void set_f2_as_vfinal_method(methodOop f2) { + assert(is_vfinal(), "flags must be set"); + set_f2((intx)f2); + } int make_flags(TosState state, int option_bits, int field_index_or_method_params); void set_flags(intx flags) { _flags = flags; } bool init_flags_atomic(intx flags);
--- a/src/share/vm/oops/typeArrayOop.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/oops/typeArrayOop.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -162,7 +162,7 @@ DEBUG_ONLY(BasicType etype = Klass::layout_helper_element_type(lh)); assert(length <= arrayOopDesc::max_array_length(etype), "no overflow"); - julong size_in_bytes = length; + julong size_in_bytes = (juint)length; size_in_bytes <<= element_shift; size_in_bytes += instance_header_size; julong size_in_words = ((size_in_bytes + (HeapWordSize-1)) >> LogHeapWordSize);
--- a/src/share/vm/opto/compile.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/compile.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -669,6 +669,7 @@ #endif set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining)); set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics")); + set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it if (ProfileTraps) { // Make sure the method being compiled gets its own MDO, @@ -936,6 +937,8 @@ set_print_assembly(PrintFrameConverterAssembly); set_parsed_irreducible_loop(false); #endif + set_has_irreducible_loop(false); // no loops + CompileWrapper cw(this); Init(/*AliasLevel=*/ 0); init_tf((*generator)()); @@ -1100,7 +1103,7 @@ if( start->is_Start() ) return start->as_Start(); } - ShouldNotReachHere(); + fatal("Did not find Start node!"); return NULL; }
--- a/src/share/vm/opto/compile.hpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/compile.hpp Thu Oct 02 08:23:19 2014 -0700 @@ -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 @@ -291,6 +291,7 @@ bool _trace_opto_output; bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing #endif + bool _has_irreducible_loop; // Found irreducible loops // JSR 292 bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. @@ -552,6 +553,8 @@ bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; } void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; } #endif + bool has_irreducible_loop() const { return _has_irreducible_loop; } + void set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; } // JSR 292 bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
--- a/src/share/vm/opto/library_call.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/library_call.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, 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 @@ -3699,8 +3699,11 @@ } -//------------------------------inline_native_hashcode-------------------- -// Build special case code for calls to hashCode on an object. +/** + * Build special case code for calls to hashCode on an object. This call may + * be virtual (invokevirtual) or bound (invokespecial). For each case we generate + * slightly different code. + */ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { assert(is_static == callee()->is_static(), "correct intrinsic selection"); assert(!(is_virtual && is_static), "either virtual, special, or static"); @@ -3708,11 +3711,9 @@ enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); - PhiNode* result_val = new(C) PhiNode(result_reg, - TypeInt::INT); + PhiNode* result_val = new(C) PhiNode(result_reg, TypeInt::INT); PhiNode* result_io = new(C) PhiNode(result_reg, Type::ABIO); - PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, - TypePtr::BOTTOM); + PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, TypePtr::BOTTOM); Node* obj = NULL; if (!is_static) { // Check for hashing null object @@ -3738,12 +3739,6 @@ return true; } - // After null check, get the object's klass. - Node* obj_klass = load_object_klass(obj); - - // This call may be virtual (invokevirtual) or bound (invokespecial). - // For each case we generate slightly different code. - // We only go to the fast case code if we pass a number of guards. The // paths which do not pass are accumulated in the slow_region. RegionNode* slow_region = new (C) RegionNode(1); @@ -3756,19 +3751,24 @@ // guard for non-virtual calls -- the caller is known to be the native // Object hashCode(). if (is_virtual) { + // After null check, get the object's klass. + Node* obj_klass = load_object_klass(obj); generate_virtual_guard(obj_klass, slow_region); } // 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()); + // The control of the load must be NULL. Otherwise, the load can move before + // the null check after castPP removal. + Node* no_ctrl = NULL; + Node* header = make_load(no_ctrl, header_addr, TypeX_X, TypeX_X->basic_type()); // Test the header to see if it is unlocked. - Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); - Node *lmasked_header = _gvn.transform( new (C) AndXNode(header, lock_mask) ); - Node *unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); - Node *chk_unlocked = _gvn.transform( new (C) CmpXNode( lmasked_header, unlocked_val)); - Node *test_unlocked = _gvn.transform( new (C) BoolNode( chk_unlocked, BoolTest::ne) ); + Node* lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); + Node* lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask)); + Node* unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); + Node* chk_unlocked = _gvn.transform(new (C) CmpXNode( lmasked_header, unlocked_val)); + Node* test_unlocked = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne)); generate_slow_guard(test_unlocked, slow_region); @@ -3776,19 +3776,19 @@ // We depend on hash_mask being at most 32 bits and avoid the use of // hash_mask_in_place because it could be larger than 32 bits in a 64-bit // vm: see markOop.hpp. - Node *hash_mask = _gvn.intcon(markOopDesc::hash_mask); - Node *hash_shift = _gvn.intcon(markOopDesc::hash_shift); - Node *hshifted_header= _gvn.transform( new (C) URShiftXNode(header, hash_shift) ); + Node* hash_mask = _gvn.intcon(markOopDesc::hash_mask); + Node* hash_shift = _gvn.intcon(markOopDesc::hash_shift); + Node* hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift)); // This hack lets the hash bits live anywhere in the mark object now, as long // as the shift drops the relevant bits into the low 32 bits. Note that // Java spec says that HashCode is an int so there's no point in capturing // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). hshifted_header = ConvX2I(hshifted_header); - Node *hash_val = _gvn.transform( new (C) AndINode(hshifted_header, hash_mask) ); - - Node *no_hash_val = _gvn.intcon(markOopDesc::no_hash); - Node *chk_assigned = _gvn.transform( new (C) CmpINode( hash_val, no_hash_val)); - Node *test_assigned = _gvn.transform( new (C) BoolNode( chk_assigned, BoolTest::eq) ); + Node* hash_val = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask)); + + Node* no_hash_val = _gvn.intcon(markOopDesc::no_hash); + Node* chk_assigned = _gvn.transform(new (C) CmpINode( hash_val, no_hash_val)); + Node* test_assigned = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq)); generate_slow_guard(test_assigned, slow_region);
--- a/src/share/vm/opto/loopTransform.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/loopTransform.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1127,6 +1127,7 @@ // Now force out all loop-invariant dominating tests. The optimizer // finds some, but we _know_ they are all useless. peeled_dom_test_elim(loop,old_new); + loop->record_for_igvn(); } //------------------------------is_invariant-----------------------------
--- a/src/share/vm/opto/loopnode.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/loopnode.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -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 @@ -266,9 +266,9 @@ // Counted loop head must be a good RegionNode with only 3 not NULL // control input edges: Self, Entry, LoopBack. - if (x->in(LoopNode::Self) == NULL || x->req() != 3) + if (x->in(LoopNode::Self) == NULL || x->req() != 3 || loop->_irreducible) { return false; - + } Node *init_control = x->in(LoopNode::EntryControl); Node *back_control = x->in(LoopNode::LoopBackControl); if (init_control == NULL || back_control == NULL) // Partially dead @@ -1522,11 +1522,11 @@ // If I have one hot backedge, peel off myself loop. // I better be the outermost loop. - if( _head->req() > 3 ) { + if (_head->req() > 3 && !_irreducible) { split_outer_loop( phase ); result = true; - } else if( !_head->is_Loop() && !_irreducible ) { + } else if (!_head->is_Loop() && !_irreducible) { // Make a new LoopNode to replace the old loop head Node *l = new (phase->C) LoopNode( _head->in(1), _head->in(2) ); l = igvn.register_new_node_with_optimizer(l, _head); @@ -2938,6 +2938,7 @@ return pre_order; } } + C->set_has_irreducible_loop(_has_irreducible_loops); } // This Node might be a decision point for loops. It is only if @@ -3171,17 +3172,16 @@ bool had_error = false; #ifdef ASSERT if (early != C->root()) { - // Make sure that there's a dominance path from use to LCA - Node* d = use; - while (d != LCA) { - d = idom(d); + // Make sure that there's a dominance path from LCA to early + Node* d = LCA; + while (d != early) { if (d == C->root()) { - tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx); - n->dump(); - use->dump(); + dump_bad_graph("Bad graph detected in compute_lca_of_uses", n, early, LCA); + tty->print_cr("*** Use %d isn't dominated by def %d ***", use->_idx, n->_idx); had_error = true; break; } + d = idom(d); } } #endif @@ -3434,6 +3434,13 @@ _igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops. } +#ifdef ASSERT + if (_verify_only && !n->is_CFG()) { + // Check def-use domination. + compute_lca_of_uses(n, get_ctrl(n), true /* verify */); + } +#endif + // CFG and pinned nodes already handled if( n->in(0) ) { if( n->in(0)->is_top() ) return; // Dead?
--- a/src/share/vm/opto/loopopts.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/loopopts.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -2684,6 +2684,7 @@ // Inhibit more partial peeling on this loop new_head_clone->set_partial_peel_loop(); C->set_major_progress(); + loop->record_for_igvn(); #if !defined(PRODUCT) if (TracePartialPeeling) {
--- a/src/share/vm/opto/memnode.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/memnode.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -292,33 +292,16 @@ int alias_idx = phase->C->get_alias_index(t_adr->is_ptr()); } -#ifdef ASSERT Node* base = NULL; - if (address->is_AddP()) + if (address->is_AddP()) { base = address->in(AddPNode::Base); + } if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) && !t_adr->isa_rawptr()) { // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true. - Compile* C = phase->C; - tty->cr(); - tty->print_cr("===== NULL+offs not RAW address ====="); - if (C->is_dead_node(this->_idx)) tty->print_cr("'this' is dead"); - if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead"); - if (C->is_dead_node(mem->_idx)) tty->print_cr("'mem' is dead"); - if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead"); - if (C->is_dead_node(base->_idx)) tty->print_cr("'base' is dead"); - tty->cr(); - base->dump(1); - tty->cr(); - this->dump(2); - tty->print("this->adr_type(): "); adr_type()->dump(); tty->cr(); - tty->print("phase->type(address): "); t_adr->dump(); tty->cr(); - tty->print("phase->type(base): "); phase->type(address)->dump(); tty->cr(); - tty->cr(); + // Skip this node optimization if its address has TOP base. + return NodeSentinel; // caller will return NULL } - assert(base == NULL || t_adr->isa_rawptr() || - !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?"); -#endif // Avoid independent memory operations Node* old_mem = mem;
--- a/src/share/vm/opto/node.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/opto/node.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -27,6 +27,7 @@ #include "memory/allocation.inline.hpp" #include "opto/cfgnode.hpp" #include "opto/connode.hpp" +#include "opto/loopnode.hpp" #include "opto/machnode.hpp" #include "opto/matcher.hpp" #include "opto/node.hpp" @@ -1225,6 +1226,7 @@ Node *top = igvn->C->top(); nstack.push(dead); + bool has_irreducible_loop = igvn->C->has_irreducible_loop(); while (nstack.size() > 0) { dead = nstack.pop(); @@ -1239,13 +1241,31 @@ assert (!use->is_Con(), "Control for Con node should be Root node."); use->set_req(0, top); // Cut dead edge to prevent processing nstack.push(use); // the dead node again. + } else if (!has_irreducible_loop && // Backedge could be alive in irreducible loop + use->is_Loop() && !use->is_Root() && // Don't kill Root (RootNode extends LoopNode) + use->in(LoopNode::EntryControl) == dead) { // Dead loop if its entry is dead + use->set_req(LoopNode::EntryControl, top); // Cut dead edge to prevent processing + use->set_req(0, top); // Cut self edge + nstack.push(use); } else { // Else found a not-dead user + // Dead if all inputs are top or null + bool dead_use = !use->is_Root(); // Keep empty graph alive for (uint j = 1; j < use->req(); j++) { - if (use->in(j) == dead) { // Turn all dead inputs into TOP + Node* in = use->in(j); + if (in == dead) { // Turn all dead inputs into TOP use->set_req(j, top); + } else if (in != NULL && !in->is_top()) { + dead_use = false; } } - igvn->_worklist.push(use); + if (dead_use) { + if (use->is_Region()) { + use->set_req(0, top); // Cut self edge + } + nstack.push(use); + } else { + igvn->_worklist.push(use); + } } // Refresh the iterator, since any number of kills might have happened. k = dead->last_outs(kmin);
--- a/src/share/vm/runtime/vmThread.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/runtime/vmThread.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -327,6 +327,9 @@ _terminate_lock->notify(); } + // Thread destructor usually does this. + ThreadLocalStorage::set_thread(NULL); + // Deletion must be done synchronously by the JNI DestroyJavaVM thread // so that the VMThread deletion completes before the main thread frees // up the CodeHeap.
--- a/src/share/vm/services/heapDumper.cpp Thu Sep 11 10:59:36 2014 -0700 +++ b/src/share/vm/services/heapDumper.cpp Thu Oct 02 08:23:19 2014 -0700 @@ -720,7 +720,7 @@ // reflection and sun.misc.Unsafe classes may have a reference to a // klassOop so filter it out. - if (o != NULL && o->is_klass()) { + if (o != NULL && o->is_perm() && o->is_klass()) { o = NULL; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/hashcode/TestHashCode.java Thu Oct 02 08:23:19 2014 -0700 @@ -0,0 +1,73 @@ +/* + * 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 8011646 + * @summary SEGV in compiled code with loop predication + * @run main/othervm -XX:-TieredCompilation -XX:CompileOnly=TestHashCode.m1,Object.hashCode TestHashCode + * + */ + +public class TestHashCode { + static class A { + int i; + } + + static class B extends A { + } + + static boolean crash = false; + + static A m2() { + if (crash) { + return null; + } + return new A(); + } + + static int m1(A aa) { + int res = 0; + for (int i = 0; i < 10; i++) { + A a = m2(); + int j = a.i; + if (aa instanceof B) { + } + res += a.hashCode(); + } + return res; + } + + public static void main(String[] args) { + A a = new A(); + for (int i = 0; i < 20000; i++) { + m1(a); + } + crash = true; + try { + m1(a); + } catch (NullPointerException e) { + System.out.println("Test passed"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/heap_inspection/TestG1ConcurrentGCHeapDump.java Thu Oct 02 08:23:19 2014 -0700 @@ -0,0 +1,108 @@ +/* + * 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 TestG1ConcurrentGCHeapDump + * @bug 8038925 + * @summary Checks that a heap dump can be made with G1 when no fullgc + * has been made + * @run main/othervm -Xms512m -Xmx1024m -XX:+ExplicitGCInvokesConcurrent TestG1ConcurrentGCHeapDump + */ +import java.util.List; +import java.util.ArrayList; +import java.util.LinkedList; + +import javax.management.MBeanServer; +import java.lang.management.ManagementFactory; +import java.lang.management.GarbageCollectorMXBean; + +import sun.management.ManagementFactoryHelper; +import com.sun.management.HotSpotDiagnosticMXBean; +import com.sun.management.VMOption; + +import java.io.IOException; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.Files; + +public class TestG1ConcurrentGCHeapDump { + + private static final String HOTSPOT_BEAN_NAME = + "com.sun.management:type=HotSpotDiagnostic"; + + private static final String G1_OLD_BEAN_NAME = + "java.lang:type=GarbageCollector,name=G1 Old Generation"; + + private static MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + private static void dumpHeap() throws IOException { + HotSpotDiagnosticMXBean hotspot_bean = + ManagementFactory.newPlatformMXBeanProxy(server, + HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class); + + Path dir = Files.createTempDirectory("JDK-8038925_"); + String file = dir + File.separator + "heapdump"; + hotspot_bean.dumpHeap(file, false); + Files.delete(Paths.get(file)); + Files.delete(dir); + } + + private static void verifyNoFullGC() throws IOException { + GarbageCollectorMXBean g1_old_bean = + ManagementFactory.newPlatformMXBeanProxy(server, + G1_OLD_BEAN_NAME, GarbageCollectorMXBean.class); + + if (g1_old_bean.getCollectionCount() != 0) { + throw new RuntimeException("A full GC has occured, this test will not work."); + } + } + + public static void main(String[] args) throws IOException { + HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); + VMOption option = diagnostic.getVMOption("UseG1GC"); + if (option.getValue().equals("false")) { + System.out.println("Skipping this test. It is only a G1 test."); + return; + } + + // Create some dead objects + ArrayList<List<Integer>> arraylist = new ArrayList<List<Integer>>(); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 100; j++) { + LinkedList<Integer> li = new LinkedList<Integer>(); + arraylist.add(li); + for (int k = 0; k < 10000; k++) { + li.add(k); + } + } + arraylist = new ArrayList<List<Integer>>(); + System.gc(); + } + // Try to dump heap + dumpHeap(); + // Make sure no full GC has happened, since test won't work if that is the case + verifyNoFullGC(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java Thu Oct 02 08:23:19 2014 -0700 @@ -0,0 +1,72 @@ +/* + * 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 8028623 + * @summary Test hashing of extended characters in Serviceability Agent. + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.JDKToolLauncher; +import com.oracle.java.testlibrary.OutputBuffer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.io.File; + +public class Test8028623 { + + public static int à = 1; + public static String dumpFile = "heap.out"; + + public static void main (String[] args) { + + System.out.println(Ã); + + try { + int pid = ProcessTools.getProcessId(); + JDKToolLauncher jmap = JDKToolLauncher.create("jmap") + .addToolArg("-F") + .addToolArg("-dump:live,format=b,file=" + dumpFile) + .addToolArg(Integer.toString(pid)); + ProcessBuilder pb = new ProcessBuilder(jmap.getCommand()); + OutputBuffer output = ProcessTools.getOutput(pb); + Process p = pb.start(); + int e = p.waitFor(); + System.out.println("stdout:"); + System.out.println(output.getStdout()); + System.out.println("stderr:"); + System.out.println(output.getStderr()); + + if (e != 0) { + throw new RuntimeException("jmap returns: " + e); + } + if (! new File(dumpFile).exists()) { + throw new RuntimeException("dump file NOT created: '" + dumpFile + "'"); + } + } catch (Throwable t) { + t.printStackTrace(); + throw new RuntimeException("Test failed with: " + t); + } + } +}