# HG changeset patch # User kizune # Date 1386065586 -14400 # Node ID 0611ce949aaac26c17eed532a3efd53b95a9eff0 # Parent c31f0cbe6d9e22a0e6f27c7557d3471500ff777e# Parent e6dfcdf37ef2623fd9f96819d54a0d038ce9be2e Merge diff -r c31f0cbe6d9e -r 0611ce949aaa .hgtags --- a/.hgtags Sun Nov 03 07:50:24 2013 +0000 +++ b/.hgtags Tue Dec 03 14:13:06 2013 +0400 @@ -390,3 +390,11 @@ 4589b398ab03aba6a5da8c06ff53603488d1b8f4 jdk8-b113 82a9cdbf683e374a76f2009352de53e16bed5a91 hs25-b56 7fd913010dbbf75260688fd2fa8964763fa49a09 jdk8-b114 +3b32d287da89a47a45d16f6d9ba5bd3cd9bf4b3e hs25-b57 +9ebaac78a8a0061fb9597e07f806498cb626cdeb jdk8-b115 +e510dfdec6dd701410f3398ed86ebcdff0cca63a hs25-b58 +52b076e6ffae247c1c7d8b7aba995195be2b6fc2 jdk8-b116 +c78d517c7ea47501b456e707afd4b78e7b5b202e hs25-b59 +f573d00213b7170c2ff856f9cd83cd148437f5b9 jdk8-b117 +abad3b2d905d9e1ad767c94baa94aba6ed5b207b hs25-b60 +c9f439732b18ea16f7e65815327d5ea7092cc258 jdk8-b118 diff -r c31f0cbe6d9e -r 0611ce949aaa agent/src/os/bsd/ps_proc.c --- a/agent/src/os/bsd/ps_proc.c Sun Nov 03 07:50:24 2013 +0000 +++ b/agent/src/os/bsd/ps_proc.c Tue Dec 03 14:13:06 2013 +0400 @@ -131,7 +131,7 @@ static bool ptrace_continue(pid_t pid, int signal) { // pass the signal to the process so we don't swallow it - if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { + if (ptrace(PT_CONTINUE, pid, NULL, signal) < 0) { print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); return false; } @@ -434,7 +434,6 @@ // attach to the process. One and only one exposed stuff struct ps_prochandle* Pgrab(pid_t pid) { struct ps_prochandle* ph = NULL; - thread_info* thr = NULL; if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) { print_debug("can't allocate memory for ps_prochandle\n"); diff -r c31f0cbe6d9e -r 0611ce949aaa agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Sun Nov 03 07:50:24 2013 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Tue Dec 03 14:13:06 2013 +0400 @@ -24,8 +24,9 @@ package sun.jvm.hotspot.tools; -import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.debugger.JVMDebugger; +import sun.jvm.hotspot.runtime.Arguments; +import sun.jvm.hotspot.runtime.VM; public class JInfo extends Tool { public JInfo() { @@ -138,14 +139,33 @@ } private void printVMFlags() { + VM.Flag[] flags = VM.getVM().getCommandLineFlags(); + System.out.print("Non-default VM flags: "); + for (VM.Flag flag : flags) { + if (flag.getOrigin() == 0) { + // only print flags which aren't their defaults + continue; + } + if (flag.isBool()) { + String onoff = flag.getBool() ? "+" : "-"; + System.out.print("-XX:" + onoff + flag.getName() + " "); + } else { + System.out.print("-XX:" + flag.getName() + "=" + + flag.getValue() + " "); + } + } + System.out.println(); + + System.out.print("Command line: "); String str = Arguments.getJVMFlags(); if (str != null) { - System.out.println(str); + System.out.print(str + " "); } str = Arguments.getJVMArgs(); if (str != null) { - System.out.println(str); + System.out.print(str); } + System.out.println(); } private int mode; diff -r c31f0cbe6d9e -r 0611ce949aaa agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Sun Nov 03 07:50:24 2013 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Tue Dec 03 14:13:06 2013 +0400 @@ -25,11 +25,11 @@ package sun.jvm.hotspot.tools; import java.io.PrintStream; -import java.util.Hashtable; -import sun.jvm.hotspot.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.HotSpotAgent; +import sun.jvm.hotspot.debugger.DebuggerException; +import sun.jvm.hotspot.debugger.JVMDebugger; +import sun.jvm.hotspot.runtime.VM; // generic command line or GUI tool. // override run & code main as shown below. @@ -147,6 +147,7 @@ } PrintStream err = System.err; + PrintStream out = System.out; int pid = 0; String coreFileName = null; @@ -180,18 +181,18 @@ try { switch (debugeeType) { case DEBUGEE_PID: - err.println("Attaching to process ID " + pid + ", please wait..."); + out.println("Attaching to process ID " + pid + ", please wait..."); agent.attach(pid); break; case DEBUGEE_CORE: - err.println("Attaching to core " + coreFileName + + out.println("Attaching to core " + coreFileName + " from executable " + executableName + ", please wait..."); agent.attach(executableName, coreFileName); break; case DEBUGEE_REMOTE: - err.println("Attaching to remote server " + remoteServer + ", please wait..."); + out.println("Attaching to remote server " + remoteServer + ", please wait..."); agent.attach(remoteServer); break; } @@ -218,7 +219,7 @@ return 1; } - err.println("Debugger attached successfully."); + out.println("Debugger attached successfully."); startInternal(); return 0; } @@ -237,14 +238,14 @@ // Remains of the start mechanism, common to both start methods. private void startInternal() { - PrintStream err = System.err; + PrintStream out = System.out; VM vm = VM.getVM(); if (vm.isCore()) { - err.println("Core build detected."); + out.println("Core build detected."); } else if (vm.isClientCompiler()) { - err.println("Client compiler detected."); + out.println("Client compiler detected."); } else if (vm.isServerCompiler()) { - err.println("Server compiler detected."); + out.println("Server compiler detected."); } else { throw new RuntimeException("Fatal error: " + "should have been able to detect core/C1/C2 build"); @@ -252,8 +253,8 @@ String version = vm.getVMRelease(); if (version != null) { - err.print("JVM version is "); - err.println(version); + out.print("JVM version is "); + out.println(version); } run(); diff -r c31f0cbe6d9e -r 0611ce949aaa make/hotspot_version --- a/make/hotspot_version Sun Nov 03 07:50:24 2013 +0000 +++ b/make/hotspot_version Tue Dec 03 14:13:06 2013 +0400 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=56 +HS_BUILD_NUMBER=60 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -365,7 +365,7 @@ return entry; } -address CppInterpreter::return_entry(TosState state, int length) { +address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { // make it look good in the debugger return CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation) + frame::pc_return_offset; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/macroAssembler_sparc.cpp --- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -3526,8 +3526,12 @@ delayed()->sub(Rtsp, Roffset, Rtsp); // Bang down shadow pages too. - // The -1 because we already subtracted 1 page. - for (int i = 0; i< StackShadowPages-1; i++) { + // At this point, (tmp-0) is the last address touched, so don't + // touch it again. (It was touched as (tmp-pagesize) but then tmp + // was post-decremented.) Skip this address by starting at i=1, and + // touch a few more pages below. N.B. It is important to touch all + // the way down to and including i=StackShadowPages. + for (int i = 1; i <= StackShadowPages; i++) { set((-i*offset)+STACK_BIAS, Rscratch); st(G0, Rtsp, Rscratch); } @@ -4099,15 +4103,19 @@ void MacroAssembler::encode_klass_not_null(Register r) { assert (UseCompressedClassPointers, "must be compressed"); - assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); - assert(r != G6_heapbase, "bad register choice"); - set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); - sub(r, G6_heapbase, r); - if (Universe::narrow_klass_shift() != 0) { - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - srlx(r, LogKlassAlignmentInBytes, r); + if (Universe::narrow_klass_base() != NULL) { + assert(r != G6_heapbase, "bad register choice"); + set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); + sub(r, G6_heapbase, r); + if (Universe::narrow_klass_shift() != 0) { + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + srlx(r, LogKlassAlignmentInBytes, r); + } + reinit_heapbase(); + } else { + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift() || Universe::narrow_klass_shift() == 0, "decode alg wrong"); + srlx(r, Universe::narrow_klass_shift(), r); } - reinit_heapbase(); } void MacroAssembler::encode_klass_not_null(Register src, Register dst) { @@ -4115,11 +4123,16 @@ encode_klass_not_null(src); } else { assert (UseCompressedClassPointers, "must be compressed"); - assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); - set((intptr_t)Universe::narrow_klass_base(), dst); - sub(src, dst, dst); - if (Universe::narrow_klass_shift() != 0) { - srlx(dst, LogKlassAlignmentInBytes, dst); + if (Universe::narrow_klass_base() != NULL) { + set((intptr_t)Universe::narrow_klass_base(), dst); + sub(src, dst, dst); + if (Universe::narrow_klass_shift() != 0) { + srlx(dst, LogKlassAlignmentInBytes, dst); + } + } else { + // shift src into dst + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift() || Universe::narrow_klass_shift() == 0, "decode alg wrong"); + srlx(src, Universe::narrow_klass_shift(), dst); } } } @@ -4129,14 +4142,16 @@ // the instructions they generate change, then this method needs to be updated. int MacroAssembler::instr_size_for_decode_klass_not_null() { assert (UseCompressedClassPointers, "only for compressed klass ptrs"); - // set + add + set - int num_instrs = insts_for_internal_set((intptr_t)Universe::narrow_klass_base()) + 1 + - insts_for_internal_set((intptr_t)Universe::narrow_ptrs_base()); - if (Universe::narrow_klass_shift() == 0) { - return num_instrs * BytesPerInstWord; - } else { // sllx - return (num_instrs + 1) * BytesPerInstWord; + int num_instrs = 1; // shift src,dst or add + if (Universe::narrow_klass_base() != NULL) { + // set + add + set + num_instrs += insts_for_internal_set((intptr_t)Universe::narrow_klass_base()) + + insts_for_internal_set((intptr_t)Universe::narrow_ptrs_base()); + if (Universe::narrow_klass_shift() != 0) { + num_instrs += 1; // sllx + } } + return num_instrs * BytesPerInstWord; } // !!! If the instructions that get generated here change then function @@ -4145,13 +4160,17 @@ // Do not add assert code to this unless you change vtableStubs_sparc.cpp // pd_code_size_limit. assert (UseCompressedClassPointers, "must be compressed"); - assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); - assert(r != G6_heapbase, "bad register choice"); - set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); - if (Universe::narrow_klass_shift() != 0) - sllx(r, LogKlassAlignmentInBytes, r); - add(r, G6_heapbase, r); - reinit_heapbase(); + if (Universe::narrow_klass_base() != NULL) { + assert(r != G6_heapbase, "bad register choice"); + set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); + if (Universe::narrow_klass_shift() != 0) + sllx(r, LogKlassAlignmentInBytes, r); + add(r, G6_heapbase, r); + reinit_heapbase(); + } else { + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift() || Universe::narrow_klass_shift() == 0, "decode alg wrong"); + sllx(r, Universe::narrow_klass_shift(), r); + } } void MacroAssembler::decode_klass_not_null(Register src, Register dst) { @@ -4161,16 +4180,21 @@ // Do not add assert code to this unless you change vtableStubs_sparc.cpp // pd_code_size_limit. assert (UseCompressedClassPointers, "must be compressed"); - assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); - if (Universe::narrow_klass_shift() != 0) { - assert((src != G6_heapbase) && (dst != G6_heapbase), "bad register choice"); - set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); - sllx(src, LogKlassAlignmentInBytes, dst); - add(dst, G6_heapbase, dst); - reinit_heapbase(); + if (Universe::narrow_klass_base() != NULL) { + if (Universe::narrow_klass_shift() != 0) { + assert((src != G6_heapbase) && (dst != G6_heapbase), "bad register choice"); + set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); + sllx(src, LogKlassAlignmentInBytes, dst); + add(dst, G6_heapbase, dst); + reinit_heapbase(); + } else { + set((intptr_t)Universe::narrow_klass_base(), dst); + add(src, dst, dst); + } } else { - set((intptr_t)Universe::narrow_klass_base(), dst); - add(src, dst, dst); + // shift/mov src into dst. + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift() || Universe::narrow_klass_shift() == 0, "decode alg wrong"); + sllx(src, Universe::narrow_klass_shift(), dst); } } } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1002,18 +1002,6 @@ // and the vm will find there should this case occur. Address callee_target_addr(G2_thread, JavaThread::callee_target_offset()); __ st_ptr(G5_method, callee_target_addr); - - if (StressNonEntrant) { - // Open a big window for deopt failure - __ save_frame(0); - __ mov(G0, L0); - Label loop; - __ bind(loop); - __ sub(L0, 1, L0); - __ br_null_short(L0, Assembler::pt, loop); - __ restore(); - } - __ jmpl(G3, 0, G0); __ delayed()->nop(); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/sparc.ad Tue Dec 03 14:13:06 2013 +0400 @@ -1660,12 +1660,16 @@ if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); - st->print_cr("\tSET Universe::narrow_klass_base,R_G6_heap_base"); - if (Universe::narrow_klass_shift() != 0) { - st->print_cr("\tSLL R_G5,3,R_G5"); + if (Universe::narrow_klass_base() != 0) { + st->print_cr("\tSET Universe::narrow_klass_base,R_G6_heap_base"); + if (Universe::narrow_klass_shift() != 0) { + st->print_cr("\tSLL R_G5,Universe::narrow_klass_shift,R_G5"); + } + st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); + st->print_cr("\tSET Universe::narrow_ptrs_base,R_G6_heap_base"); + } else { + st->print_cr("\tSLL R_G5,Universe::narrow_klass_shift,R_G5"); } - st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); - st->print_cr("\tSET Universe::narrow_ptrs_base,R_G6_heap_base"); } else { st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); } @@ -2912,6 +2916,9 @@ __ bind(LSkip2); } + // We have no guarantee that on 64 bit the higher half of limit_reg is 0 + __ signx(limit_reg); + __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); __ br(Assembler::equal, true, Assembler::pn, Ldone); __ delayed()->mov(O7, result_reg); // result is difference in lengths @@ -2969,6 +2976,9 @@ Register chr1_reg = result_reg; Register chr2_reg = tmp1_reg; + // We have no guarantee that on 64 bit the higher half of limit_reg is 0 + __ signx(limit_reg); + //check for alignment and position the pointers to the ends __ or3(str1_reg, str2_reg, chr1_reg); __ andcc(chr1_reg, 0x3, chr1_reg); diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -153,13 +153,9 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { - TosState incoming_state = state; +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { + address entry = __ pc(); - Label cont; - address compiled_entry = __ pc(); - - address entry = __ pc(); #if !defined(_LP64) && defined(COMPILER2) // All return values are where we want them, except for Longs. C2 returns // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. @@ -170,14 +166,12 @@ // do this here. Unfortunately if we did a rethrow we'd see an machepilog node // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - if (incoming_state == ltos) { + if (state == ltos) { __ srl (G1, 0, O1); __ srlx(G1, 32, O0); } #endif // !_LP64 && COMPILER2 - __ bind(cont); - // The callee returns with the stack possibly adjusted by adapter transition // We remove that possible adjustment here. // All interpreter local registers are untouched. Any result is passed back @@ -186,29 +180,18 @@ __ mov(Llast_SP, SP); // Remove any adapter added stack space. - Label L_got_cache, L_giant_index; const Register cache = G3_scratch; - const Register size = G1_scratch; - if (EnableInvokeDynamic) { - __ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode. - __ cmp_and_br_short(G1_scratch, Bytecodes::_invokedynamic, Assembler::equal, Assembler::pn, L_giant_index); - } - __ get_cache_and_index_at_bcp(cache, G1_scratch, 1); - __ bind(L_got_cache); - __ ld_ptr(cache, ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset(), size); - __ and3(size, 0xFF, size); // argument size in words - __ sll(size, Interpreter::logStackElementSize, size); // each argument size in bytes - __ add(Lesp, size, Lesp); // pop arguments + const Register index = G1_scratch; + __ get_cache_and_index_at_bcp(cache, index, 1, index_size); + + const Register flags = cache; + __ ld_ptr(cache, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset(), flags); + const Register parameter_size = flags; + __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words + __ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes + __ add(Lesp, parameter_size, Lesp); // pop arguments __ dispatch_next(state, step); - // out of the main line of code... - if (EnableInvokeDynamic) { - __ bind(L_giant_index); - __ get_cache_and_index_at_bcp(cache, G1_scratch, 1, sizeof(u4)); - __ ba_short(L_got_cache); - } - return entry; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/sparc/vm/templateTable_sparc.cpp --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2932,9 +2932,7 @@ ConstantPoolCacheEntry::verify_tos_state_shift(); // load return address { - const address table_addr = (is_invokeinterface || is_invokedynamic) ? - (address)Interpreter::return_5_addrs_by_index_table() : - (address)Interpreter::return_3_addrs_by_index_table(); + const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); AddressLiteral table(table_addr); __ set(table, temp); __ sll(ra, LogBytesPerWord, ra); @@ -2984,7 +2982,7 @@ __ verify_oop(O0_recv); // get return address - AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); + AddressLiteral table(Interpreter::invoke_return_entry_table()); __ set(table, Rtemp); __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type // Make sure we don't need to mask Rret after the above shift @@ -3026,7 +3024,7 @@ __ profile_final_call(O4); // get return address - AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); + AddressLiteral table(Interpreter::invoke_return_entry_table()); __ set(table, Rtemp); __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type // Make sure we don't need to mask Rret after the above shift diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1468,19 +1468,18 @@ addr = new LIR_Address(src.result(), offset, type); } - if (data != dst) { - __ move(data, dst); - data = dst; - } + // Because we want a 2-arg form of xchg and xadd + __ move(data, dst); + if (x->is_add()) { - __ xadd(LIR_OprFact::address(addr), data, dst, LIR_OprFact::illegalOpr); + __ xadd(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr); } else { if (is_obj) { // Do the pre-write barrier, if any. pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ xchg(LIR_OprFact::address(addr), data, dst, LIR_OprFact::illegalOpr); + __ xchg(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr); if (is_obj) { // Seems to be a precise address post_barrier(LIR_OprFact::address(addr), data); diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -367,7 +367,7 @@ return entry; } -address CppInterpreter::return_entry(TosState state, int length) { +address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { // make it look good in the debugger return CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -196,7 +196,7 @@ void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); - movl(reg, Address(rsi, bcp_offset)); + load_unsigned_short(reg, Address(rsi, bcp_offset)); bswapl(reg); shrl(reg, 16); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -192,7 +192,7 @@ Register reg, int bcp_offset) { assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); - movl(reg, Address(r13, bcp_offset)); + load_unsigned_short(reg, Address(r13, bcp_offset)); bswapl(reg); shrl(reg, 16); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1381,8 +1381,12 @@ jcc(Assembler::greater, loop); // Bang down shadow pages too. - // The -1 because we already subtracted 1 page. - for (int i = 0; i< StackShadowPages-1; i++) { + // At this point, (tmp-0) is the last address touched, so don't + // touch it again. (It was touched as (tmp-pagesize) but then tmp + // was post-decremented.) Skip this address by starting at i=1, and + // touch a few more pages below. N.B. It is important to touch all + // the way down to and including i=StackShadowPages. + for (int i = 1; i <= StackShadowPages; i++) { // this could be any sized move but this is can be a debugging crumb // so the bigger the better. movptr(Address(tmp, (-i*os::vm_page_size())), size ); @@ -5049,25 +5053,32 @@ } void MacroAssembler::encode_klass_not_null(Register r) { - assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); - // Use r12 as a scratch register in which to temporarily load the narrow_klass_base. - assert(r != r12_heapbase, "Encoding a klass in r12"); - mov64(r12_heapbase, (int64_t)Universe::narrow_klass_base()); - subq(r, r12_heapbase); + if (Universe::narrow_klass_base() != NULL) { + // Use r12 as a scratch register in which to temporarily load the narrow_klass_base. + assert(r != r12_heapbase, "Encoding a klass in r12"); + mov64(r12_heapbase, (int64_t)Universe::narrow_klass_base()); + subq(r, r12_heapbase); + } if (Universe::narrow_klass_shift() != 0) { assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); shrq(r, LogKlassAlignmentInBytes); } - reinit_heapbase(); + if (Universe::narrow_klass_base() != NULL) { + reinit_heapbase(); + } } void MacroAssembler::encode_klass_not_null(Register dst, Register src) { if (dst == src) { encode_klass_not_null(src); } else { - mov64(dst, (int64_t)Universe::narrow_klass_base()); - negq(dst); - addq(dst, src); + if (Universe::narrow_klass_base() != NULL) { + mov64(dst, (int64_t)Universe::narrow_klass_base()); + negq(dst); + addq(dst, src); + } else { + movptr(dst, src); + } if (Universe::narrow_klass_shift() != 0) { assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); shrq(dst, LogKlassAlignmentInBytes); @@ -5081,15 +5092,19 @@ // generate change, then this method needs to be updated. int MacroAssembler::instr_size_for_decode_klass_not_null() { assert (UseCompressedClassPointers, "only for compressed klass ptrs"); - // mov64 + addq + shlq? + mov64 (for reinit_heapbase()). - return (Universe::narrow_klass_shift() == 0 ? 20 : 24); + if (Universe::narrow_klass_base() != NULL) { + // mov64 + addq + shlq? + mov64 (for reinit_heapbase()). + return (Universe::narrow_klass_shift() == 0 ? 20 : 24); + } else { + // longest load decode klass function, mov64, leaq + return 16; + } } // !!! If the instructions that get generated here change then function // instr_size_for_decode_klass_not_null() needs to get updated. void MacroAssembler::decode_klass_not_null(Register r) { // Note: it will change flags - assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert(r != r12_heapbase, "Decoding a klass in r12"); // Cannot assert, unverified entry point counts instructions (see .ad file) @@ -5100,14 +5115,15 @@ shlq(r, LogKlassAlignmentInBytes); } // Use r12 as a scratch register in which to temporarily load the narrow_klass_base. - mov64(r12_heapbase, (int64_t)Universe::narrow_klass_base()); - addq(r, r12_heapbase); - reinit_heapbase(); + if (Universe::narrow_klass_base() != NULL) { + mov64(r12_heapbase, (int64_t)Universe::narrow_klass_base()); + addq(r, r12_heapbase); + reinit_heapbase(); + } } void MacroAssembler::decode_klass_not_null(Register dst, Register src) { // Note: it will change flags - assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); assert (UseCompressedClassPointers, "should only be used for compressed headers"); if (dst == src) { decode_klass_not_null(dst); @@ -5115,7 +5131,6 @@ // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. - mov64(dst, (int64_t)Universe::narrow_klass_base()); if (Universe::narrow_klass_shift() != 0) { assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -3001,6 +3001,10 @@ // sp should be pointing at the return address to the caller (3) + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); + // Stack bang to make sure there's enough room for these interpreter frames. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); @@ -3020,9 +3024,6 @@ __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); __ movl(counter, rbx); - // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter // frame and the stack walking of interpreter_sender will get the unextended sp @@ -3220,6 +3221,10 @@ // sp should be pointing at the return address to the caller (3) + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); + // Stack bang to make sure there's enough room for these interpreter frames. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); @@ -3240,9 +3245,6 @@ __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); __ movl(counter, rbx); - // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter // frame and the stack walking of interpreter_sender will get the unextended sp diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -3471,6 +3471,10 @@ // rsp should be pointing at the return address to the caller (3) + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); + // Stack bang to make sure there's enough room for these interpreter frames. if (UseStackBanging) { __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); @@ -3489,9 +3493,6 @@ // Load counter into rdx __ movl(rdx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); - // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); - // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter // frame and the stack walking of interpreter_sender will get the unextended sp @@ -3663,6 +3664,10 @@ // rsp should be pointing at the return address to the caller (3) + // Pick up the initial fp we should save + // restore rbp before stack bang because if stack overflow is thrown it needs to be pushed (and preserved) + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); + // Stack bang to make sure there's enough room for these interpreter frames. if (UseStackBanging) { __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); @@ -3670,27 +3675,16 @@ } // Load address of array of frame pcs into rcx (address*) - __ movptr(rcx, - Address(rdi, - Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); + __ movptr(rcx, Address(rdi, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); // Trash the return pc __ addptr(rsp, wordSize); // Load address of array of frame sizes into rsi (intptr_t*) - __ movptr(rsi, Address(rdi, - Deoptimization::UnrollBlock:: - frame_sizes_offset_in_bytes())); + __ movptr(rsi, Address(rdi, Deoptimization::UnrollBlock:: frame_sizes_offset_in_bytes())); // Counter - __ movl(rdx, Address(rdi, - Deoptimization::UnrollBlock:: - number_of_frames_offset_in_bytes())); // (int) - - // Pick up the initial fp we should save - __ movptr(rbp, - Address(rdi, - Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); + __ movl(rdx, Address(rdi, Deoptimization::UnrollBlock:: number_of_frames_offset_in_bytes())); // (int) // Now adjust the caller's stack to make up for the extra locals but // record the original sp so that we can save it in the skeletal @@ -3700,9 +3694,7 @@ const Register sender_sp = r8; __ mov(sender_sp, rsp); - __ movl(rbx, Address(rdi, - Deoptimization::UnrollBlock:: - caller_adjustment_offset_in_bytes())); // (int) + __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock:: caller_adjustment_offset_in_bytes())); // (int) __ subptr(rsp, rbx); // Push interpreter frames in a loop diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -150,13 +150,12 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { - TosState incoming_state = state; +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); #ifdef COMPILER2 // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases - if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { + if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) { for (int i = 1; i < 8; i++) { __ ffree(i); } @@ -164,7 +163,7 @@ __ empty_FPU_stack(); } #endif - if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) { + if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) { __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled"); } else { __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled"); @@ -172,12 +171,12 @@ // In SSE mode, interpreter returns FP results in xmm0 but they need // to end up back on the FPU so it can operate on them. - if (incoming_state == ftos && UseSSE >= 1) { + if (state == ftos && UseSSE >= 1) { __ subptr(rsp, wordSize); __ movflt(Address(rsp, 0), xmm0); __ fld_s(Address(rsp, 0)); __ addptr(rsp, wordSize); - } else if (incoming_state == dtos && UseSSE >= 2) { + } else if (state == dtos && UseSSE >= 2) { __ subptr(rsp, 2*wordSize); __ movdbl(Address(rsp, 0), xmm0); __ fld_d(Address(rsp, 0)); @@ -194,33 +193,22 @@ __ restore_bcp(); __ restore_locals(); - if (incoming_state == atos) { + if (state == atos) { Register mdp = rbx; Register tmp = rcx; __ profile_return_type(mdp, rax, tmp); } - Label L_got_cache, L_giant_index; - if (EnableInvokeDynamic) { - __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic); - __ jcc(Assembler::equal, L_giant_index); - } - __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u2)); - __ bind(L_got_cache); - __ movl(rbx, Address(rbx, rcx, - Address::times_ptr, ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset())); - __ andptr(rbx, 0xFF); - __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale())); + const Register cache = rbx; + const Register index = rcx; + __ get_cache_and_index_at_bcp(cache, index, 1, index_size); + + const Register flags = cache; + __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); + __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); + __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); __ dispatch_next(state, step); - // out of the main line of code... - if (EnableInvokeDynamic) { - __ bind(L_giant_index); - __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u4)); - __ jmp(L_got_cache); - } - return entry; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -166,7 +166,7 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); // Restore stack bottom in case i2c adjusted stack @@ -183,28 +183,16 @@ __ profile_return_type(mdp, rax, tmp); } - Label L_got_cache, L_giant_index; - if (EnableInvokeDynamic) { - __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic); - __ jcc(Assembler::equal, L_giant_index); - } - __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u2)); - __ bind(L_got_cache); - __ movl(rbx, Address(rbx, rcx, - Address::times_ptr, - in_bytes(ConstantPoolCache::base_offset()) + - 3 * wordSize)); - __ andl(rbx, 0xFF); - __ lea(rsp, Address(rsp, rbx, Address::times_8)); + const Register cache = rbx; + const Register index = rcx; + __ get_cache_and_index_at_bcp(cache, index, 1, index_size); + + const Register flags = cache; + __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); + __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); + __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); __ dispatch_next(state, step); - // out of the main line of code... - if (EnableInvokeDynamic) { - __ bind(L_giant_index); - __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u4)); - __ jmp(L_got_cache); - } - return entry; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/templateTable_x86_32.cpp --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -558,7 +558,7 @@ void TemplateTable::locals_index_wide(Register reg) { - __ movl(reg, at_bcp(2)); + __ load_unsigned_short(reg, at_bcp(2)); __ bswapl(reg); __ shrl(reg, 16); __ negptr(reg); @@ -1552,7 +1552,11 @@ InvocationCounter::counter_offset(); // Load up EDX with the branch displacement - __ movl(rdx, at_bcp(1)); + if (is_wide) { + __ movl(rdx, at_bcp(1)); + } else { + __ load_signed_short(rdx, at_bcp(1)); + } __ bswapl(rdx); if (!is_wide) __ sarl(rdx, 16); LP64_ONLY(__ movslq(rdx, rdx)); @@ -2925,9 +2929,7 @@ ConstantPoolCacheEntry::verify_tos_state_shift(); // load return address { - const address table_addr = (is_invokeinterface || is_invokedynamic) ? - (address)Interpreter::return_5_addrs_by_index_table() : - (address)Interpreter::return_3_addrs_by_index_table(); + const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); ExternalAddress table(table_addr); __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -568,7 +568,7 @@ } void TemplateTable::locals_index_wide(Register reg) { - __ movl(reg, at_bcp(2)); + __ load_unsigned_short(reg, at_bcp(2)); __ bswapl(reg); __ shrl(reg, 16); __ negptr(reg); @@ -1575,7 +1575,11 @@ InvocationCounter::counter_offset(); // Load up edx with the branch displacement - __ movl(rdx, at_bcp(1)); + if (is_wide) { + __ movl(rdx, at_bcp(1)); + } else { + __ load_signed_short(rdx, at_bcp(1)); + } __ bswapl(rdx); if (!is_wide) { @@ -2980,9 +2984,7 @@ ConstantPoolCacheEntry::verify_tos_state_shift(); // load return address { - const address table_addr = (is_invokeinterface || is_invokedynamic) ? - (address)Interpreter::return_5_addrs_by_index_table() : - (address)Interpreter::return_3_addrs_by_index_table(); + const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); ExternalAddress table(table_addr); __ lea(rscratch1, table); __ movptr(flags, Address(rscratch1, flags, Address::times_ptr)); diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1006,7 +1006,7 @@ istate->set_stack_limit(stack_base - method->max_stack() - 1); } -address CppInterpreter::return_entry(TosState state, int length) { +address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { ShouldNotCallThis(); return NULL; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/cpu/zero/vm/globals_zero.hpp --- a/src/cpu/zero/vm/globals_zero.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/cpu/zero/vm/globals_zero.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -57,6 +57,8 @@ // 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); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) #endif // CPU_ZERO_VM_GLOBALS_ZERO_HPP diff -r c31f0cbe6d9e -r 0611ce949aaa src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/os/bsd/vm/os_bsd.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -945,17 +945,15 @@ // Used by VMSelfDestructTimer and the MemProfiler. double os::elapsedTime() { - return (double)(os::elapsed_counter()) * 0.000001; + return ((double)os::elapsed_counter()) / os::elapsed_frequency(); } 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; + return javaTimeNanos() - initial_time_count; } jlong os::elapsed_frequency() { - return (1000 * 1000); + return NANOSECS_PER_SEC; // nanosecond resolution } bool os::supports_vtime() { return true; } @@ -3582,7 +3580,7 @@ Bsd::_main_thread = pthread_self(); Bsd::clock_init(); - initial_time_count = os::elapsed_counter(); + initial_time_count = javaTimeNanos(); #ifdef __APPLE__ // XXXDARWIN diff -r c31f0cbe6d9e -r 0611ce949aaa src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/os/linux/vm/os_linux.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1333,17 +1333,15 @@ // Used by VMSelfDestructTimer and the MemProfiler. double os::elapsedTime() { - return (double)(os::elapsed_counter()) * 0.000001; + return ((double)os::elapsed_counter()) / os::elapsed_frequency(); // nanosecond resolution } 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; + return javaTimeNanos() - initial_time_count; } jlong os::elapsed_frequency() { - return (1000 * 1000); + return NANOSECS_PER_SEC; // nanosecond resolution } bool os::supports_vtime() { return true; } @@ -4750,7 +4748,7 @@ Linux::_main_thread = pthread_self(); Linux::clock_init(); - initial_time_count = os::elapsed_counter(); + initial_time_count = javaTimeNanos(); // pthread_condattr initialization for monotonic clock int status; diff -r c31f0cbe6d9e -r 0611ce949aaa src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -79,6 +79,15 @@ # include #endif +// needed by current_stack_region() workaround for Mavericks +#if defined(__APPLE__) +# include +# include +# include +# define DEFAULT_MAIN_THREAD_STACK_PAGES 2048 +# define OS_X_10_9_0_KERNEL_MAJOR_VERSION 13 +#endif + #ifdef AMD64 #define SPELL_REG_SP "rsp" #define SPELL_REG_FP "rbp" @@ -828,6 +837,21 @@ pthread_t self = pthread_self(); void *stacktop = pthread_get_stackaddr_np(self); *size = pthread_get_stacksize_np(self); + // workaround for OS X 10.9.0 (Mavericks) + // pthread_get_stacksize_np returns 128 pages even though the actual size is 2048 pages + if (pthread_main_np() == 1) { + if ((*size) < (DEFAULT_MAIN_THREAD_STACK_PAGES * (size_t)getpagesize())) { + char kern_osrelease[256]; + size_t kern_osrelease_size = sizeof(kern_osrelease); + int ret = sysctlbyname("kern.osrelease", kern_osrelease, &kern_osrelease_size, NULL, 0); + if (ret == 0) { + // get the major number, atoi will ignore the minor amd micro portions of the version string + if (atoi(kern_osrelease) >= OS_X_10_9_0_KERNEL_MAJOR_VERSION) { + *size = (DEFAULT_MAIN_THREAD_STACK_PAGES*getpagesize()); + } + } + } + } *bottom = (address) stacktop - *size; #elif defined(__OpenBSD__) stack_t ss; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/asm/assembler.cpp --- a/src/share/vm/asm/assembler.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/asm/assembler.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -122,7 +122,7 @@ void AbstractAssembler::generate_stack_overflow_check( int frame_size_in_bytes) { if (UseStackBanging) { // Each code entry causes one stack bang n pages down the stack where n - // is configurable by StackBangPages. The setting depends on the maximum + // is configurable by StackShadowPages. The setting depends on the maximum // depth of VM call stack or native before going back into java code, // since only java code can raise a stack overflow exception using the // stack banging mechanism. The VM and native code does not detect stack diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1873,7 +1873,7 @@ // number of implementors for decl_interface is 0 or 1. If // it's 0 then no class implements decl_interface and there's // no point in inlining. - if (!holder->is_loaded() || decl_interface->nof_implementors() != 1) { + if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_default_methods()) { singleton = NULL; } } @@ -4338,6 +4338,11 @@ #endif // PRODUCT void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder, Values* obj_args, bool inlined) { + // A default method's holder is an interface + if (known_holder != NULL && known_holder->is_interface()) { + assert(known_holder->is_instance_klass() && ((ciInstanceKlass*)known_holder)->has_default_methods(), "should be default method"); + known_holder = NULL; + } append(new ProfileCall(method(), bci(), callee, recv, known_holder, obj_args, inlined)); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2574,8 +2574,25 @@ __ jump(x->default_sux()); } - -ciKlass* LIRGenerator::profile_arg_type(ciMethodData* md, int md_base_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k) { +/** + * Emit profiling code if needed for arguments, parameters, return value types + * + * @param md MDO the code will update at runtime + * @param md_base_offset common offset in the MDO for this profile and subsequent ones + * @param md_offset offset in the MDO (on top of md_base_offset) for this profile + * @param profiled_k current profile + * @param obj IR node for the object to be profiled + * @param mdp register to hold the pointer inside the MDO (md + md_base_offset). + * Set once we find an update to make and use for next ones. + * @param not_null true if we know obj cannot be null + * @param signature_at_call_k signature at call for obj + * @param callee_signature_k signature of callee for obj + * at call and callee signatures differ at method handle call + * @return the only klass we know will ever be seen at this profile point + */ +ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md_offset, intptr_t profiled_k, + Value obj, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, + ciKlass* callee_signature_k) { ciKlass* result = NULL; bool do_null = !not_null && !TypeEntries::was_null_seen(profiled_k); bool do_update = !TypeEntries::is_type_unknown(profiled_k); @@ -2590,9 +2607,9 @@ if (do_update) { // try to find exact type, using CHA if possible, so that loading // the klass from the object can be avoided - ciType* type = arg->exact_type(); + ciType* type = obj->exact_type(); if (type == NULL) { - type = arg->declared_type(); + type = obj->declared_type(); type = comp->cha_exact_type(type); } assert(type == NULL || type->is_klass(), "type should be class"); @@ -2608,23 +2625,33 @@ ciKlass* exact_signature_k = NULL; if (do_update) { // Is the type from the signature exact (the only one possible)? - exact_signature_k = signature_k->exact_klass(); + exact_signature_k = signature_at_call_k->exact_klass(); if (exact_signature_k == NULL) { - exact_signature_k = comp->cha_exact_type(signature_k); + exact_signature_k = comp->cha_exact_type(signature_at_call_k); } else { result = exact_signature_k; - do_update = false; // Known statically. No need to emit any code: prevent // LIR_Assembler::emit_profile_type() from emitting useless code profiled_k = ciTypeEntries::with_status(result, profiled_k); } if (exact_signature_k != NULL && exact_klass != exact_signature_k) { - assert(exact_klass == NULL, "arg and signature disagree?"); + assert(exact_klass == NULL, "obj and signature disagree?"); // sometimes the type of the signature is better than the best type // the compiler has exact_klass = exact_signature_k; - do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass; } + if (callee_signature_k != NULL && + callee_signature_k != signature_at_call_k) { + ciKlass* improved_klass = callee_signature_k->exact_klass(); + if (improved_klass == NULL) { + improved_klass = comp->cha_exact_type(callee_signature_k); + } + if (improved_klass != NULL && exact_klass != improved_klass) { + assert(exact_klass == NULL, "obj and signature disagree?"); + exact_klass = exact_signature_k; + } + } + do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass; } if (!do_null && !do_update) { @@ -2640,7 +2667,7 @@ __ leal(LIR_OprFact::address(base_type_address), mdp); } } - LIRItem value(arg, this); + LIRItem value(obj, this); value.load_item(); __ profile_type(new LIR_Address(mdp, md_offset, T_METADATA), value.result(), exact_klass, profiled_k, new_pointer_register(), not_null, exact_signature_k != NULL); @@ -2665,9 +2692,9 @@ if (t == T_OBJECT || t == T_ARRAY) { intptr_t profiled_k = parameters->type(j); Local* local = x->state()->local_at(java_index)->as_Local(); - ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), - in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)), - profiled_k, local, mdp, false, local->declared_type()->as_klass()); + ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), + in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)), + profiled_k, local, mdp, false, local->declared_type()->as_klass(), NULL); // If the profile is known statically set it once for all and do not emit any code if (exact != NULL) { md->set_parameter_type(j, exact); @@ -3129,19 +3156,28 @@ Bytecodes::Code bc = x->method()->java_code_at_bci(bci); int start = 0; int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments(); - if (x->nb_profiled_args() < stop) { - // if called through method handle invoke, some arguments may have been popped - stop = x->nb_profiled_args(); + if (x->inlined() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) { + // first argument is not profiled at call (method handle invoke) + assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected"); + start = 1; } - ciSignature* sig = x->callee()->signature(); + ciSignature* callee_signature = x->callee()->signature(); // method handle call to virtual method bool has_receiver = x->inlined() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc); - ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL); - for (int i = 0; i < stop; i++) { + ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL); + + bool ignored_will_link; + ciSignature* signature_at_call = NULL; + x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call); + ciSignatureStream signature_at_call_stream(signature_at_call); + + // if called through method handle invoke, some arguments may have been popped + for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) { int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset()); - ciKlass* exact = profile_arg_type(md, base_offset, off, - args->type(i), x->profiled_arg_at(i+start), mdp, - !x->arg_needs_null_check(i+start), sig_stream.next_klass()); + ciKlass* exact = profile_type(md, base_offset, off, + args->type(i), x->profiled_arg_at(i+start), mdp, + !x->arg_needs_null_check(i+start), + signature_at_call_stream.next_klass(), callee_signature_stream.next_klass()); if (exact != NULL) { md->set_argument_type(bci, i, exact); } @@ -3176,8 +3212,8 @@ int bci = x->bci_of_invoke(); Bytecodes::Code bc = x->method()->java_code_at_bci(bci); // The first parameter is the receiver so that's what we start - // with if it exists. On exception if method handle call to - // virtual method has receiver in the args list + // with if it exists. One exception is method handle call to + // virtual method: the receiver is in the args list if (arg == NULL || !Bytecodes::has_receiver(bc)) { i = 1; arg = x->profiled_arg_at(0); @@ -3186,9 +3222,9 @@ int k = 0; // to iterate on the profile data for (;;) { intptr_t profiled_k = parameters->type(k); - ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), - in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)), - profiled_k, arg, mdp, not_null, sig_stream.next_klass()); + ciKlass* exact = profile_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), + in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)), + profiled_k, arg, mdp, not_null, sig_stream.next_klass(), NULL); // If the profile is known statically set it once for all and do not emit any code if (exact != NULL) { md->set_parameter_type(k, exact); @@ -3247,9 +3283,16 @@ assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type"); ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret(); LIR_Opr mdp = LIR_OprFact::illegalOpr; - ciKlass* exact = profile_arg_type(md, 0, md->byte_offset_of_slot(data, ret->type_offset()), - ret->type(), x->ret(), mdp, - !x->needs_null_check(), x->callee()->signature()->return_type()->as_klass()); + + bool ignored_will_link; + ciSignature* signature_at_call = NULL; + x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call); + + ciKlass* exact = profile_type(md, 0, md->byte_offset_of_slot(data, ret->type_offset()), + ret->type(), x->ret(), mdp, + !x->needs_null_check(), + signature_at_call->return_type()->as_klass(), + x->callee()->signature()->return_type()->as_klass()); if (exact != NULL) { md->set_return_type(bci, exact); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/c1/c1_LIRGenerator.hpp --- a/src/share/vm/c1/c1_LIRGenerator.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/c1/c1_LIRGenerator.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -434,7 +434,9 @@ void do_ThreadIDIntrinsic(Intrinsic* x); void do_ClassIDIntrinsic(Intrinsic* x); #endif - ciKlass* profile_arg_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k); + ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, + Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, + ciKlass* callee_signature_k); void profile_arguments(ProfileCall* x); void profile_parameters(Base* x); void profile_parameters_at_call(ProfileCall* x); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/c1/c1_LinearScan.cpp --- a/src/share/vm/c1/c1_LinearScan.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/c1/c1_LinearScan.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1138,8 +1138,10 @@ } } } - - } else if (opr_type != T_LONG) { + // We want to sometimes use logical operations on pointers, in particular in GC barriers. + // Since 64bit logical operations do not current support operands on stack, we have to make sure + // T_OBJECT doesn't get spilled along with T_LONG. + } else if (opr_type != T_LONG LP64_ONLY(&& opr_type != T_OBJECT)) { // integer instruction (note: long operands must always be in register) switch (op->code()) { case lir_cmp: diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/c1/c1_globals.hpp --- a/src/share/vm/c1/c1_globals.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/c1/c1_globals.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -341,9 +341,6 @@ diagnostic(bool, C1PatchInvokeDynamic, true, \ "Patch invokedynamic appendix not known at compile time") \ \ - develop(intx, MaxForceInlineLevel, 100, \ - "maximum number of nested @ForceInline calls that are inlined") \ - \ // Read default values for c1 globals diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/ci/ciEnv.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -935,7 +935,9 @@ // Prevent SystemDictionary::add_to_hierarchy from running // and invalidating our dependencies until we install this method. + // No safepoints are allowed. Otherwise, class redefinition can occur in between. MutexLocker ml(Compile_lock); + No_Safepoint_Verifier nsv; // Change in Jvmti state may invalidate compilation. if (!failing() && @@ -1001,31 +1003,15 @@ // Free codeBlobs code_buffer->free_blob(); - // stress test 6243940 by immediately making the method - // non-entrant behind the system's back. This has serious - // side effects on the code cache and is not meant for - // general stress testing - if (nm != NULL && StressNonEntrant) { - MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); - NativeJump::patch_verified_entry(nm->entry_point(), nm->verified_entry_point(), - SharedRuntime::get_handle_wrong_method_stub()); - } - - if (nm == NULL) { - // The CodeCache is full. Print out warning and disable compilation. - record_failure("code cache is full"); - { - MutexUnlocker ml(Compile_lock); - MutexUnlocker locker(MethodCompileQueue_lock); - CompileBroker::handle_full_code_cache(); - } - } else { + if (nm != NULL) { nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_wide_vectors(has_wide_vectors); // Record successful registration. // (Put nm into the task handle *before* publishing to the Java heap.) - if (task() != NULL) task()->set_code(nm); + if (task() != NULL) { + task()->set_code(nm); + } if (entry_bci == InvocationEntryBci) { if (TieredCompilation) { @@ -1036,11 +1022,11 @@ char *method_name = method->name_and_sig_as_C_string(); tty->print_cr("Replacing method %s", method_name); } - if (old != NULL ) { + if (old != NULL) { old->make_not_entrant(); } } - if (TraceNMethodInstalls ) { + if (TraceNMethodInstalls) { ResourceMark rm; char *method_name = method->name_and_sig_as_C_string(); ttyLocker ttyl; @@ -1051,7 +1037,7 @@ // Allow the code to be executed method->set_code(method, nm); } else { - if (TraceNMethodInstalls ) { + if (TraceNMethodInstalls) { ResourceMark rm; char *method_name = method->name_and_sig_as_C_string(); ttyLocker ttyl; @@ -1061,15 +1047,18 @@ entry_bci); } method->method_holder()->add_osr_nmethod(nm); - } } - } - // JVMTI -- compiled method notification (must be done outside lock) + } // safepoints are allowed again + if (nm != NULL) { + // JVMTI -- compiled method notification (must be done outside lock) nm->post_compiled_method_load_event(); + } else { + // The CodeCache is full. Print out warning and disable compilation. + record_failure("code cache is full"); + CompileBroker::handle_full_code_cache(); } - } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -57,6 +57,7 @@ _init_state = ik->init_state(); _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); + _has_default_methods = ik->has_default_methods(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _implementor = NULL; // we will fill these lazily diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/ci/ciInstanceKlass.hpp --- a/src/share/vm/ci/ciInstanceKlass.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/ci/ciInstanceKlass.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -52,6 +52,7 @@ bool _has_finalizer; bool _has_subklass; bool _has_nonstatic_fields; + bool _has_default_methods; ciFlags _flags; jint _nonstatic_field_size; @@ -171,6 +172,11 @@ } } + bool has_default_methods() { + assert(is_loaded(), "must be loaded"); + return _has_default_methods; + } + ciInstanceKlass* get_canonical_holder(int offset); ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/ci/ciMethodData.hpp --- a/src/share/vm/ci/ciMethodData.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/ci/ciMethodData.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -77,7 +77,9 @@ static ciKlass* valid_ciklass(intptr_t k) { if (!TypeEntries::is_type_none(k) && !TypeEntries::is_type_unknown(k)) { - return (ciKlass*)TypeEntries::klass_part(k); + ciKlass* res = (ciKlass*)TypeEntries::klass_part(k); + assert(res != NULL, "invalid"); + return res; } else { return NULL; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -4080,7 +4080,7 @@ // Generate any default methods - default methods are interface methods // that have a default implementation. This is new with Lambda project. - if (has_default_methods && !access_flags.is_interface() ) { + if (has_default_methods ) { DefaultMethods::generate_default_methods( this_klass(), &all_mirandas, CHECK_(nullHandle)); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/classLoaderData.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -131,6 +131,17 @@ } } +void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { + // Lock to avoid classes being modified/added/removed during iteration + MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); + for (Klass* k = _klasses; k != NULL; k = k->next_link()) { + // Do not filter ArrayKlass oops here... + if (k->oop_is_array() || (k->oop_is_instance() && InstanceKlass::cast(k)->is_loaded())) { + klass_closure->do_klass(k); + } + } +} + void ClassLoaderData::classes_do(void f(InstanceKlass*)) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k->oop_is_instance()) { @@ -600,6 +611,12 @@ } } +void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) { + for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { + cld->loaded_classes_do(klass_closure); + } +} + void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/classLoaderData.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -78,6 +78,7 @@ static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim); static void classes_do(KlassClosure* klass_closure); static void classes_do(void f(Klass* const)); + static void loaded_classes_do(KlassClosure* klass_closure); static void classes_unloading_do(void f(Klass* const)); static bool do_unloading(BoolObjectClosure* is_alive); @@ -186,6 +187,7 @@ bool keep_alive() const { return _keep_alive; } bool is_alive(BoolObjectClosure* is_alive_closure) const; void classes_do(void f(Klass*)); + void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); // Deallocate free list during class unloading. diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/defaultMethods.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -171,8 +171,12 @@ } bool is_cancelled() const { return _cancelled; } + // This code used to skip interface classes because their only + // superclass was j.l.Object which would be also covered by class + // superclass hierarchy walks. Now that the starting point can be + // an interface, we must ensure we catch j.l.Object as the super. static bool has_super(InstanceKlass* cls) { - return cls->super() != NULL && !cls->is_interface(); + return cls->super() != NULL; } Node* node_at_depth(int i) const { @@ -391,24 +395,32 @@ return; } + // Qualified methods are maximally-specific methods + // These include public, instance concrete (=default) and abstract methods GrowableArray qualified_methods; + int num_defaults = 0; + int default_index = -1; + int qualified_index = -1; for (int i = 0; i < _members.length(); ++i) { Pair entry = _members.at(i); if (entry.second == QUALIFIED) { qualified_methods.append(entry.first); + qualified_index++; + if (entry.first->is_default_method()) { + num_defaults++; + default_index = qualified_index; + + } } } if (qualified_methods.length() == 0) { _exception_message = generate_no_defaults_message(CHECK); _exception_name = vmSymbols::java_lang_AbstractMethodError(); - } else if (qualified_methods.length() == 1) { - // leave abstract methods alone, they will be found via normal search path - Method* method = qualified_methods.at(0); - if (!method->is_abstract()) { - _selected_target = qualified_methods.at(0); - } - } else { + // If only one qualified method is default, select that + } else if (num_defaults == 1) { + _selected_target = qualified_methods.at(default_index); + } else if (num_defaults > 1) { _exception_message = generate_conflicts_message(&qualified_methods,CHECK); _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); if (TraceDefaultMethods) { @@ -416,6 +428,7 @@ tty->print_cr(""); } } + // leave abstract methods alone, they will be found via normal search path } bool contains_signature(Symbol* query) { @@ -695,8 +708,10 @@ Method* m = iklass->find_method(_method_name, _method_signature); // private interface methods are not candidates for default methods // invokespecial to private interface methods doesn't use default method logic + // The overpasses are your supertypes' errors, we do not include them // future: take access controls into account for superclass methods - if (m != NULL && !m->is_static() && (!iklass->is_interface() || m->is_public())) { + if (m != NULL && !m->is_static() && !m->is_overpass() && + (!iklass->is_interface() || m->is_public())) { if (_family == NULL) { _family = new StatefulMethodFamily(); } @@ -772,7 +787,8 @@ #ifndef PRODUCT if (TraceDefaultMethods) { ResourceMark rm; // be careful with these! - tty->print_cr("Class %s requires default method processing", + tty->print_cr("%s %s requires default method processing", + klass->is_interface() ? "Interface" : "Class", klass->name()->as_klass_external_name()); PrintHierarchy printer; printer.run(klass); @@ -797,7 +813,7 @@ } #ifndef PRODUCT if (TraceDefaultMethods) { - tty->print_cr("Creating overpasses..."); + tty->print_cr("Creating defaults and overpasses..."); } #endif // ndef PRODUCT @@ -1067,7 +1083,9 @@ klass->set_initial_method_idnum(new_size); ClassLoaderData* cld = klass->class_loader_data(); - MetadataFactory::free_array(cld, original_methods); + if (original_methods ->length() > 0) { + MetadataFactory::free_array(cld, original_methods); + } if (original_ordering->length() > 0) { klass->set_method_ordering(merged_ordering); MetadataFactory::free_array(cld, original_ordering); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/metadataOnStackMark.cpp --- a/src/share/vm/classfile/metadataOnStackMark.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -27,8 +27,10 @@ #include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" #include "oops/metadata.hpp" +#include "prims/jvmtiImpl.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.hpp" +#include "services/threadService.hpp" #include "utilities/growableArray.hpp" @@ -48,6 +50,8 @@ Threads::metadata_do(Metadata::mark_on_stack); CodeCache::alive_nmethods_do(nmethod::mark_on_stack); CompileBroker::mark_on_stack(); + JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack); + ThreadService::metadata_do(Metadata::mark_on_stack); } MetadataOnStackMark::~MetadataOnStackMark() { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -141,7 +141,6 @@ /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \ do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \ do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ @@ -173,8 +172,6 @@ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \ \ - do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \ - \ /* Preload boxing klasses */ \ do_klass(Boolean_klass, java_lang_Boolean, Pre ) \ do_klass(Character_klass, java_lang_Character, Pre ) \ diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/verifier.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -188,10 +188,8 @@ bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { Symbol* name = klass->name(); Klass* refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); - Klass* lambda_magic_klass = SystemDictionary::lambda_MagicLambdaImpl_klass(); bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); - bool is_lambda = lambda_magic_klass != NULL && klass->is_subtype_of(lambda_magic_klass); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class @@ -215,9 +213,7 @@ // NOTE: this is called too early in the bootstrapping process to be // guarded by Universe::is_gte_jdk14x_version()/UseNewReflection. // Also for lambda generated code, gte jdk8 - (!is_reflect || VerifyReflectionBytecodes) && - (!is_lambda || VerifyLambdaBytecodes) - ); + (!is_reflect || VerifyReflectionBytecodes)); } Symbol* Verifier::inference_verify( diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -273,7 +273,6 @@ template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \ template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \ template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \ - template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/code/nmethod.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -618,21 +618,18 @@ // record this nmethod as dependent on this klass InstanceKlass::cast(klass)->add_dependent_nmethod(nm); } - } - NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); - if (PrintAssembly && nm != NULL) { - Disassembler::decode(nm); + NOT_PRODUCT(nmethod_stats.note_nmethod(nm)); + if (PrintAssembly) { + Disassembler::decode(nm); + } } } - - // verify nmethod - debug_only(if (nm) nm->verify();) // might block - + // Do verification and logging outside CodeCache_lock. if (nm != NULL) { + // Safepoints in nmethod::verify aren't allowed because nm hasn't been installed yet. + DEBUG_ONLY(nm->verify();) nm->log_new_nmethod(); } - - // done return nm; } @@ -1262,7 +1259,7 @@ set_osr_link(NULL); //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods - NMethodSweeper::notify(); + NMethodSweeper::report_state_change(this); } void nmethod::invalidate_osr_method() { @@ -1296,7 +1293,9 @@ } } -// Common functionality for both make_not_entrant and make_zombie +/** + * Common functionality for both make_not_entrant and make_zombie + */ bool nmethod::make_not_entrant_or_zombie(unsigned int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); assert(!is_zombie(), "should not already be a zombie"); @@ -1420,9 +1419,7 @@ tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); } - // Make sweeper aware that there is a zombie method that needs to be removed - NMethodSweeper::notify(); - + NMethodSweeper::report_state_change(this); return true; } @@ -2395,20 +2392,23 @@ void nmethod::verify_interrupt_point(address call_site) { - // This code does not work in release mode since - // owns_lock only is available in debug mode. - CompiledIC* ic = NULL; - Thread *cur = Thread::current(); - if (CompiledIC_lock->owner() == cur || - ((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) && - SafepointSynchronize::is_at_safepoint())) { - ic = CompiledIC_at(this, call_site); - CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); - } else { - MutexLocker ml_verify (CompiledIC_lock); - ic = CompiledIC_at(this, call_site); + // Verify IC only when nmethod installation is finished. + bool is_installed = (method()->code() == this) // nmethod is in state 'alive' and installed + || !this->is_in_use(); // nmethod is installed, but not in 'alive' state + if (is_installed) { + Thread *cur = Thread::current(); + if (CompiledIC_lock->owner() == cur || + ((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) && + SafepointSynchronize::is_at_safepoint())) { + CompiledIC_at(this, call_site); + CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); + } else { + MutexLocker ml_verify (CompiledIC_lock); + CompiledIC_at(this, call_site); + } } - PcDesc* pd = pc_desc_at(ic->end_of_call()); + + PcDesc* pd = pc_desc_at(nativeCall_at(call_site)->return_address()); assert(pd != NULL, "PcDesc must exist"); for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(), pd->obj_decode_offset(), pd->should_reexecute(), diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -126,6 +126,7 @@ bool CompileBroker::_initialized = false; volatile bool CompileBroker::_should_block = false; +volatile jint CompileBroker::_print_compilation_warning = 0; volatile jint CompileBroker::_should_compile_new_jobs = run_compilation; // The installed compiler(s) @@ -780,6 +781,10 @@ void CompileBroker::compilation_init() { _last_method_compiled[0] = '\0'; + // No need to initialize compilation system if we do not use it. + if (!UseCompiler) { + return; + } #ifndef SHARK // Set the interface to the current compiler(s). int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple); @@ -2023,11 +2028,10 @@ #endif } -// ------------------------------------------------------------------ -// CompileBroker::handle_full_code_cache -// -// The CodeCache is full. Print out warning and disable compilation or -// try code cache cleaning so compilation can continue later. +/** + * The CodeCache is full. Print out warning and disable compilation + * or try code cache cleaning so compilation can continue later. + */ void CompileBroker::handle_full_code_cache() { UseInterpreter = true; if (UseCompiler || AlwaysCompileLoopMethods ) { @@ -2044,12 +2048,9 @@ xtty->stamp(); xtty->end_elem(); } - warning("CodeCache is full. Compiler has been disabled."); - warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); CodeCache::report_codemem_full(); - #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { codecache_print(/* detailed= */ true); @@ -2062,17 +2063,22 @@ // Since code cache is full, immediately stop new compiles if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) { NMethodSweeper::log_sweep("disable_compiler"); - - // Switch to 'vm_state'. This ensures that possibly_sweep() can be called - // without having to consider the state in which the current thread is. - ThreadInVMfromUnknown in_vm; - NMethodSweeper::possibly_sweep(); } + // Switch to 'vm_state'. This ensures that possibly_sweep() can be called + // without having to consider the state in which the current thread is. + ThreadInVMfromUnknown in_vm; + NMethodSweeper::possibly_sweep(); } else { disable_compilation_forever(); } + + // Print warning only once + if (should_print_compiler_warning()) { + warning("CodeCache is full. Compiler has been disabled."); + warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); + codecache_print(/* detailed= */ true); + } } - codecache_print(/* detailed= */ true); } // ------------------------------------------------------------------ diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/compiler/compileBroker.hpp --- a/src/share/vm/compiler/compileBroker.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/compiler/compileBroker.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -315,6 +315,8 @@ static int _sum_nmethod_code_size; static long _peak_compilation_time; + static volatile jint _print_compilation_warning; + static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS); static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level); @@ -418,7 +420,11 @@ return _should_compile_new_jobs == shutdown_compilaton; } static void handle_full_code_cache(); - + // Ensures that warning is only printed once. + static bool should_print_compiler_warning() { + jint old = Atomic::cmpxchg(1, &_print_compilation_warning, 0); + return old == 0; + } // Return total compilation ticks static jlong total_compilation_ticks() { return _perf_total_compilation != NULL ? _perf_total_compilation->get_value() : 0; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -47,8 +47,9 @@ // ConcurrentMarkSweepPolicy methods // -ConcurrentMarkSweepPolicy::ConcurrentMarkSweepPolicy() { - initialize_all(); +void ConcurrentMarkSweepPolicy::initialize_alignments() { + _space_alignment = _gen_alignment = (uintx)Generation::GenGrain; + _heap_alignment = compute_heap_alignment(); } void ConcurrentMarkSweepPolicy::initialize_generations() { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -29,10 +29,11 @@ class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy { protected: + void initialize_alignments(); void initialize_generations(); public: - ConcurrentMarkSweepPolicy(); + ConcurrentMarkSweepPolicy() {} ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return this; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -594,9 +594,9 @@ _verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"), _completed_initialization(false), _collector_policy(cp), - _should_unload_classes(false), + _should_unload_classes(CMSClassUnloadingEnabled), _concurrent_cycles_since_last_unload(0), - _roots_scanning_options(0), + _roots_scanning_options(SharedHeap::SO_None), _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding), _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding), _gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()), @@ -788,14 +788,6 @@ && _survivor_chunk_index == 0), "Error"); - // Choose what strong roots should be scanned depending on verification options - if (!CMSClassUnloadingEnabled) { - // If class unloading is disabled we want to include all classes into the root set. - add_root_scanning_option(SharedHeap::SO_AllClasses); - } else { - add_root_scanning_option(SharedHeap::SO_SystemClasses); - } - NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;) _gc_counters = new CollectorCounters("CMS", 1); _completed_initialization = true; @@ -2532,6 +2524,9 @@ // Snapshot the soft reference policy to be used in this collection cycle. ref_processor()->setup_policy(clear_all_soft_refs); + // Decide if class unloading should be done + update_should_unload_classes(); + bool init_mark_was_synchronous = false; // until proven otherwise while (_collectorState != Idling) { if (TraceCMSState) { @@ -3310,7 +3305,10 @@ || VerifyBeforeExit; const int rso = SharedHeap::SO_Strings | SharedHeap::SO_CodeCache; + // We set the proper root for this CMS cycle here. if (should_unload_classes()) { // Should unload classes this cycle + remove_root_scanning_option(SharedHeap::SO_AllClasses); + add_root_scanning_option(SharedHeap::SO_SystemClasses); remove_root_scanning_option(rso); // Shrink the root set appropriately set_verifying(should_verify); // Set verification state for this cycle return; // Nothing else needs to be done at this time @@ -3318,6 +3316,9 @@ // Not unloading classes this cycle assert(!should_unload_classes(), "Inconsitency!"); + remove_root_scanning_option(SharedHeap::SO_SystemClasses); + add_root_scanning_option(SharedHeap::SO_AllClasses); + if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { // Include symbols, strings and code cache elements to prevent their resurrection. add_root_scanning_option(rso); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2008,7 +2008,7 @@ size_t init_byte_size = collector_policy()->initial_heap_byte_size(); size_t max_byte_size = collector_policy()->max_heap_byte_size(); - size_t heap_alignment = collector_policy()->max_alignment(); + size_t heap_alignment = collector_policy()->heap_alignment(); // Ensure that the sizes are properly aligned. Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); @@ -6656,13 +6656,18 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing(obj); - assert(!hr->isHumongous(), "code root in humongous region?"); + assert(!hr->continuesHumongous(), + err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT + " starting at "HR_FORMAT, + _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); // HeapRegion::add_strong_code_root() avoids adding duplicate // entries but having duplicates is OK since we "mark" nmethods // as visited when we scan the strong code root lists during the GC. hr->add_strong_code_root(_nm); - assert(hr->rem_set()->strong_code_roots_list_contains(_nm), "add failed?"); + assert(hr->rem_set()->strong_code_roots_list_contains(_nm), + err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT, + _nm, HR_FORMAT_PARAMS(hr))); } } @@ -6683,9 +6688,15 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing(obj); - assert(!hr->isHumongous(), "code root in humongous region?"); + assert(!hr->continuesHumongous(), + err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT + " starting at "HR_FORMAT, + _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); + hr->remove_strong_code_root(_nm); - assert(!hr->rem_set()->strong_code_roots_list_contains(_nm), "remove failed?"); + assert(!hr->rem_set()->strong_code_roots_list_contains(_nm), + err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT, + _nm, HR_FORMAT_PARAMS(hr))); } } @@ -6716,7 +6727,9 @@ class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure { public: bool doHeapRegion(HeapRegion *hr) { - assert(!hr->isHumongous(), "humongous region in collection set?"); + assert(!hr->isHumongous(), + err_msg("humongous region "HR_FORMAT" should not have been added to collection set", + HR_FORMAT_PARAMS(hr))); hr->migrate_strong_code_roots(); return false; } @@ -6796,9 +6809,13 @@ bool doHeapRegion(HeapRegion *hr) { HeapRegionRemSet* hrrs = hr->rem_set(); - if (hr->isHumongous()) { - // Code roots should never be attached to a humongous region - assert(hrrs->strong_code_roots_list_length() == 0, "sanity"); + if (hr->continuesHumongous()) { + // Code roots should never be attached to a continuation of a humongous region + assert(hrrs->strong_code_roots_list_length() == 0, + err_msg("code roots should never be attached to continuations of humongous region "HR_FORMAT + " starting at "HR_FORMAT", but has "INT32_FORMAT, + HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()), + hrrs->strong_code_roots_list_length())); return false; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -313,27 +313,38 @@ // for the first time during initialization. _reserve_regions = 0; - initialize_all(); _collectionSetChooser = new CollectionSetChooser(); - _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags +} + +void G1CollectorPolicy::initialize_alignments() { + _space_alignment = HeapRegion::GrainBytes; + size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable); + size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); + _heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size); } void G1CollectorPolicy::initialize_flags() { - _min_alignment = HeapRegion::GrainBytes; - size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name()); - size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); - _max_alignment = MAX3(card_table_alignment, _min_alignment, page_size); + if (G1HeapRegionSize != HeapRegion::GrainBytes) { + FLAG_SET_ERGO(uintx, G1HeapRegionSize, HeapRegion::GrainBytes); + } + if (SurvivorRatio < 1) { vm_exit_during_initialization("Invalid survivor ratio specified"); } CollectorPolicy::initialize_flags(); + _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags } -G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) { - assert(G1NewSizePercent <= G1MaxNewSizePercent, "Min larger than max"); - assert(G1NewSizePercent > 0 && G1NewSizePercent < 100, "Min out of bounds"); - assert(G1MaxNewSizePercent > 0 && G1MaxNewSizePercent < 100, "Max out of bounds"); +void G1CollectorPolicy::post_heap_initialize() { + uintx max_regions = G1CollectedHeap::heap()->max_regions(); + size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes; + if (max_young_size != MaxNewSize) { + FLAG_SET_ERGO(uintx, MaxNewSize, max_young_size); + } +} +G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true), + _min_desired_young_length(0), _max_desired_young_length(0) { if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); @@ -344,8 +355,13 @@ } } - if (FLAG_IS_CMDLINE(NewSize) && FLAG_IS_CMDLINE(MaxNewSize) && NewSize > MaxNewSize) { - vm_exit_during_initialization("Initial young gen size set larger than the maximum young gen size"); + if (NewSize > MaxNewSize) { + if (FLAG_IS_CMDLINE(MaxNewSize)) { + warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " + "A new max generation size of " SIZE_FORMAT "k will be used.", + NewSize/K, MaxNewSize/K, NewSize/K); + } + MaxNewSize = NewSize; } if (FLAG_IS_CMDLINE(NewSize)) { @@ -378,34 +394,48 @@ return MAX2(1U, default_value); } -void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) { - assert(new_number_of_heap_regions > 0, "Heap must be initialized"); +void G1YoungGenSizer::recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length) { + assert(number_of_heap_regions > 0, "Heap must be initialized"); switch (_sizer_kind) { case SizerDefaults: - _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions); - _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions); + *min_young_length = calculate_default_min_length(number_of_heap_regions); + *max_young_length = calculate_default_max_length(number_of_heap_regions); break; case SizerNewSizeOnly: - _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions); - _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length); + *max_young_length = calculate_default_max_length(number_of_heap_regions); + *max_young_length = MAX2(*min_young_length, *max_young_length); break; case SizerMaxNewSizeOnly: - _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions); - _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length); + *min_young_length = calculate_default_min_length(number_of_heap_regions); + *min_young_length = MIN2(*min_young_length, *max_young_length); break; case SizerMaxAndNewSize: // Do nothing. Values set on the command line, don't update them at runtime. break; case SizerNewRatio: - _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1); - _max_desired_young_length = _min_desired_young_length; + *min_young_length = number_of_heap_regions / (NewRatio + 1); + *max_young_length = *min_young_length; break; default: ShouldNotReachHere(); } - assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); + assert(*min_young_length <= *max_young_length, "Invalid min/max young gen size values"); +} + +uint G1YoungGenSizer::max_young_length(uint number_of_heap_regions) { + // We need to pass the desired values because recalculation may not update these + // values in some cases. + uint temp = _min_desired_young_length; + uint result = _max_desired_young_length; + recalculate_min_max_young_length(number_of_heap_regions, &temp, &result); + return result; +} + +void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) { + recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length, + &_max_desired_young_length); } void G1CollectorPolicy::init() { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -136,8 +136,16 @@ uint calculate_default_min_length(uint new_number_of_heap_regions); uint calculate_default_max_length(uint new_number_of_heap_regions); + // Update the given values for minimum and maximum young gen length in regions + // given the number of heap regions depending on the kind of sizing algorithm. + void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length); + public: G1YoungGenSizer(); + // Calculate the maximum length of the young gen given the number of regions + // depending on the sizing algorithm. + uint max_young_length(uint number_of_heap_regions); + void heap_size_changed(uint new_number_of_heap_regions); uint min_desired_young_length() { return _min_desired_young_length; @@ -165,13 +173,9 @@ G1MMUTracker* _mmu_tracker; + void initialize_alignments(); void initialize_flags(); - void initialize_all() { - initialize_flags(); - initialize_size_info(); - } - CollectionSetChooser* _collectionSetChooser; double _full_collection_start_sec; @@ -217,7 +221,6 @@ return _during_marking; } -private: enum PredictionConstants { TruncatedSeqLength = 10 }; @@ -665,8 +668,6 @@ BarrierSet::Name barrier_set_name() { return BarrierSet::G1SATBCTLogging; } - GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; } - bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0); // Record the start and end of an evacuation pause. @@ -934,6 +935,7 @@ // Calculates survivor space parameters. void update_survivors_policy(); + virtual void post_heap_initialize(); }; // This should move to some place more general... diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -377,11 +377,6 @@ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); dcqs.concatenate_logs(); - if (G1CollectedHeap::use_parallel_gc_threads()) { - // Don't set the number of workers here. It will be set - // when the task is run - // _seq_task->set_n_termination((int)n_workers()); - } guarantee( _cards_scanned == NULL, "invariant" ); _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC); for (uint i = 0; i < n_workers(); ++i) { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/heapRegion.cpp --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -174,11 +174,6 @@ region_size = MAX_REGION_SIZE; } - if (region_size != G1HeapRegionSize) { - // Update the flag to make sure that PrintFlagsFinal logs the correct value - FLAG_SET_ERGO(uintx, G1HeapRegionSize, region_size); - } - // And recalculate the log. region_size_log = log2_long((jlong) region_size); @@ -606,7 +601,9 @@ void HeapRegion::migrate_strong_code_roots() { assert(in_collection_set(), "only collection set regions"); - assert(!isHumongous(), "not humongous regions"); + assert(!isHumongous(), + err_msg("humongous region "HR_FORMAT" should not have been added to collection set", + HR_FORMAT_PARAMS(this))); HeapRegionRemSet* hrrs = rem_set(); hrrs->migrate_strong_code_roots(); @@ -727,12 +724,11 @@ return; } - // An H-region should have an empty strong code root list - if (isHumongous()) { + if (continuesHumongous()) { if (strong_code_roots_length > 0) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous " - "but has "INT32_FORMAT" code root entries", - bottom(), end(), strong_code_roots_length); + gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous " + "region but has "INT32_FORMAT" code root entries", + HR_FORMAT_PARAMS(this), strong_code_roots_length); *failures = true; } return; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1004,7 +1004,9 @@ void HeapRegionRemSet::migrate_strong_code_roots() { assert(hr()->in_collection_set(), "only collection set regions"); - assert(!hr()->isHumongous(), "not humongous regions"); + assert(!hr()->isHumongous(), + err_msg("humongous region "HR_FORMAT" should not have been added to the collection set", + HR_FORMAT_PARAMS(hr()))); ResourceMark rm; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc_implementation/parallelScavenge/adjoiningGenerations.hpp" #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp" +#include "gc_implementation/parallelScavenge/generationSizer.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" // If boundary moving is being used, create the young gen and old @@ -32,15 +33,17 @@ // the old behavior otherwise (with PSYoungGen and PSOldGen). AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs, - size_t init_low_byte_size, - size_t min_low_byte_size, - size_t max_low_byte_size, - size_t init_high_byte_size, - size_t min_high_byte_size, - size_t max_high_byte_size, + GenerationSizer* policy, size_t alignment) : - _virtual_spaces(old_young_rs, min_low_byte_size, - min_high_byte_size, alignment) { + _virtual_spaces(old_young_rs, policy->min_gen1_size(), + policy->min_gen0_size(), alignment) { + size_t init_low_byte_size = policy->initial_gen1_size(); + size_t min_low_byte_size = policy->min_gen1_size(); + size_t max_low_byte_size = policy->max_gen1_size(); + size_t init_high_byte_size = policy->initial_gen0_size(); + size_t min_high_byte_size = policy->min_gen0_size(); + size_t max_high_byte_size = policy->max_gen0_size(); + assert(min_low_byte_size <= init_low_byte_size && init_low_byte_size <= max_low_byte_size, "Parameter check"); assert(min_high_byte_size <= init_high_byte_size && diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -28,6 +28,7 @@ #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp" #include "gc_implementation/parallelScavenge/asPSOldGen.hpp" #include "gc_implementation/parallelScavenge/asPSYoungGen.hpp" +#include "gc_implementation/parallelScavenge/generationSizer.hpp" // Contains two generations that both use an AdjoiningVirtualSpaces. @@ -56,14 +57,7 @@ bool request_young_gen_expansion(size_t desired_change_in_bytes); public: - AdjoiningGenerations(ReservedSpace rs, - size_t init_low_byte_size, - size_t min_low_byte_size, - size_t max_low_byte_size, - size_t init_high_byte_size, - size_t min_high_byte_size, - size_t max_high_bytes_size, - size_t alignment); + AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment); // Accessors PSYoungGen* young_gen() { return _young_gen; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -54,7 +54,6 @@ int level) : PSOldGen(initial_size, min_size, size_limit, gen_name, level), _gen_size_limit(size_limit) - {} ASPSOldGen::ASPSOldGen(PSVirtualSpace* vs, @@ -65,13 +64,11 @@ int level) : PSOldGen(initial_size, min_size, size_limit, gen_name, level), _gen_size_limit(size_limit) - { _virtual_space = vs; } void ASPSOldGen::initialize_work(const char* perf_data_name, int level) { - PSOldGen::initialize_work(perf_data_name, level); // The old gen can grow to gen_size_limit(). _reserve reflects only @@ -94,7 +91,7 @@ ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); size_t result = gen_size_limit() - virtual_space()->committed_size(); - size_t result_aligned = align_size_down(result, heap->old_gen_alignment()); + size_t result_aligned = align_size_down(result, heap->generation_alignment()); return result_aligned; } @@ -105,7 +102,7 @@ } ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t gen_alignment = heap->old_gen_alignment(); + const size_t gen_alignment = heap->generation_alignment(); PSAdaptiveSizePolicy* policy = heap->size_policy(); const size_t working_size = used_in_bytes() + (size_t) policy->avg_promoted()->padded_average(); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -70,13 +70,12 @@ } size_t ASPSYoungGen::available_for_expansion() { - size_t current_committed_size = virtual_space()->committed_size(); assert((gen_size_limit() >= current_committed_size), "generation size limit is wrong"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); size_t result = gen_size_limit() - current_committed_size; - size_t result_aligned = align_size_down(result, heap->young_gen_alignment()); + size_t result_aligned = align_size_down(result, heap->generation_alignment()); return result_aligned; } @@ -85,7 +84,6 @@ // Future implementations could check the survivors and if to_space is in the // right place (below from_space), take a chunk from to_space. size_t ASPSYoungGen::available_for_contraction() { - size_t uncommitted_bytes = virtual_space()->uncommitted_size(); if (uncommitted_bytes != 0) { return uncommitted_bytes; @@ -94,8 +92,8 @@ if (eden_space()->is_empty()) { // Respect the minimum size for eden and for the young gen as a whole. ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t eden_alignment = heap->intra_heap_alignment(); - const size_t gen_alignment = heap->young_gen_alignment(); + const size_t eden_alignment = heap->space_alignment(); + const size_t gen_alignment = heap->generation_alignment(); assert(eden_space()->capacity_in_bytes() >= eden_alignment, "Alignment is wrong"); @@ -121,7 +119,6 @@ gclog_or_tty->print_cr(" gen_avail %d K", gen_avail/K); } return result_aligned; - } return 0; @@ -132,7 +129,7 @@ // to_space can be. size_t ASPSYoungGen::available_to_live() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t alignment = heap->intra_heap_alignment(); + const size_t alignment = heap->space_alignment(); // Include any space that is committed but is not in eden. size_t available = pointer_delta(eden_space()->bottom(), @@ -296,7 +293,7 @@ assert(eden_start < from_start, "Cannot push into from_space"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t alignment = heap->intra_heap_alignment(); + const size_t alignment = heap->space_alignment(); const bool maintain_minimum = (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001, 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 "gc_implementation/parallelScavenge/generationSizer.hpp" +#include "memory/collectorPolicy.hpp" + +void GenerationSizer::trace_gen_sizes(const char* const str) { + if (TracePageSizes) { + tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " " + SIZE_FORMAT "," SIZE_FORMAT " " + SIZE_FORMAT, + str, + _min_gen1_size / K, _max_gen1_size / K, + _min_gen0_size / K, _max_gen0_size / K, + _max_heap_byte_size / K); + } +} + +void GenerationSizer::initialize_alignments() { + _space_alignment = _gen_alignment = default_gen_alignment(); + _heap_alignment = compute_heap_alignment(); +} + +void GenerationSizer::initialize_flags() { + // Do basic sizing work + TwoGenerationCollectorPolicy::initialize_flags(); + + assert(UseSerialGC || + !FLAG_IS_DEFAULT(ParallelGCThreads) || + (ParallelGCThreads > 0), + "ParallelGCThreads should be set before flag initialization"); + + // The survivor ratio's are calculated "raw", unlike the + // default gc, which adds 2 to the ratio value. We need to + // make sure the values are valid before using them. + if (MinSurvivorRatio < 3) { + FLAG_SET_ERGO(uintx, MinSurvivorRatio, 3); + } + + if (InitialSurvivorRatio < 3) { + FLAG_SET_ERGO(uintx, InitialSurvivorRatio, 3); + } +} + +void GenerationSizer::initialize_size_info() { + trace_gen_sizes("ps heap raw"); + const size_t page_sz = os::page_size_for_region(_min_heap_byte_size, + _max_heap_byte_size, + 8); + + // Can a page size be something else than a power of two? + assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2"); + size_t new_alignment = round_to(page_sz, _gen_alignment); + if (new_alignment != _gen_alignment) { + _gen_alignment = new_alignment; + _space_alignment = new_alignment; + // Redo everything from the start + initialize_flags(); + } + TwoGenerationCollectorPolicy::initialize_size_info(); + + trace_gen_sizes("ps heap rnd"); +} diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -31,41 +31,17 @@ // TwoGenerationCollectorPolicy. Lets reuse it! class GenerationSizer : public TwoGenerationCollectorPolicy { - public: - GenerationSizer() { - // Partial init only! - initialize_flags(); - initialize_size_info(); - } + private: - void initialize_flags() { - // Do basic sizing work - TwoGenerationCollectorPolicy::initialize_flags(); + void trace_gen_sizes(const char* const str); - assert(UseSerialGC || - !FLAG_IS_DEFAULT(ParallelGCThreads) || - (ParallelGCThreads > 0), - "ParallelGCThreads should be set before flag initialization"); + // The alignment used for boundary between young gen and old gen + static size_t default_gen_alignment() { return 64 * K * HeapWordSize; } - // The survivor ratio's are calculated "raw", unlike the - // default gc, which adds 2 to the ratio value. We need to - // make sure the values are valid before using them. - if (MinSurvivorRatio < 3) { - MinSurvivorRatio = 3; - } + protected: - if (InitialSurvivorRatio < 3) { - InitialSurvivorRatio = 3; - } - } - - size_t min_young_gen_size() { return _min_gen0_size; } - size_t young_gen_size() { return _initial_gen0_size; } - size_t max_young_gen_size() { return _max_gen0_size; } - - size_t min_old_gen_size() { return _min_gen1_size; } - size_t old_gen_size() { return _initial_gen1_size; } - size_t max_old_gen_size() { return _max_gen1_size; } + void initialize_alignments(); + void initialize_flags(); + void initialize_size_info(); }; - #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GENERATIONSIZER_HPP diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -52,76 +52,20 @@ ParallelScavengeHeap* ParallelScavengeHeap::_psh = NULL; GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL; -static void trace_gen_sizes(const char* const str, - size_t og_min, size_t og_max, - size_t yg_min, size_t yg_max) -{ - if (TracePageSizes) { - tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT, - str, - og_min / K, og_max / K, - yg_min / K, yg_max / K, - (og_max + yg_max) / K); - } -} - jint ParallelScavengeHeap::initialize() { CollectedHeap::pre_initialize(); - // Cannot be initialized until after the flags are parsed - // GenerationSizer flag_parser; + // Initialize collector policy _collector_policy = new GenerationSizer(); - - size_t yg_min_size = _collector_policy->min_young_gen_size(); - size_t yg_max_size = _collector_policy->max_young_gen_size(); - size_t og_min_size = _collector_policy->min_old_gen_size(); - size_t og_max_size = _collector_policy->max_old_gen_size(); - - trace_gen_sizes("ps heap raw", - og_min_size, og_max_size, - yg_min_size, yg_max_size); - - const size_t og_page_sz = os::page_size_for_region(yg_min_size + og_min_size, - yg_max_size + og_max_size, - 8); - - const size_t og_align = set_alignment(_old_gen_alignment, og_page_sz); - const size_t yg_align = set_alignment(_young_gen_alignment, og_page_sz); + _collector_policy->initialize_all(); - // Update sizes to reflect the selected page size(s). - // - // NEEDS_CLEANUP. The default TwoGenerationCollectorPolicy uses NewRatio; it - // should check UseAdaptiveSizePolicy. Changes from generationSizer could - // move to the common code. - yg_min_size = align_size_up(yg_min_size, yg_align); - yg_max_size = align_size_up(yg_max_size, yg_align); - size_t yg_cur_size = - align_size_up(_collector_policy->young_gen_size(), yg_align); - yg_cur_size = MAX2(yg_cur_size, yg_min_size); + const size_t heap_size = _collector_policy->max_heap_byte_size(); - og_min_size = align_size_up(og_min_size, og_align); - // Align old gen size down to preserve specified heap size. - assert(og_align == yg_align, "sanity"); - og_max_size = align_size_down(og_max_size, og_align); - og_max_size = MAX2(og_max_size, og_min_size); - size_t og_cur_size = - align_size_down(_collector_policy->old_gen_size(), og_align); - og_cur_size = MAX2(og_cur_size, og_min_size); - - trace_gen_sizes("ps heap rnd", - og_min_size, og_max_size, - yg_min_size, yg_max_size); - - const size_t heap_size = og_max_size + yg_max_size; - - ReservedSpace heap_rs = Universe::reserve_heap(heap_size, og_align); - + ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment()); MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtJavaHeap); - os::trace_page_sizes("ps main", og_min_size + yg_min_size, - og_max_size + yg_max_size, og_page_sz, + os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(), + heap_size, generation_alignment(), heap_rs.base(), heap_rs.size()); if (!heap_rs.is_reserved()) { @@ -142,12 +86,6 @@ return JNI_ENOMEM; } - // Initial young gen size is 4 Mb - // - // XXX - what about flag_parser.young_gen_size()? - const size_t init_young_size = align_size_up(4 * M, yg_align); - yg_cur_size = MAX2(MIN2(init_young_size, yg_max_size), yg_cur_size); - // Make up the generations // Calculate the maximum size that a generation can grow. This // includes growth into the other generation. Note that the @@ -157,14 +95,7 @@ double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0; double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0; - _gens = new AdjoiningGenerations(heap_rs, - og_cur_size, - og_min_size, - og_max_size, - yg_cur_size, - yg_min_size, - yg_max_size, - yg_align); + _gens = new AdjoiningGenerations(heap_rs, _collector_policy, generation_alignment()); _old_gen = _gens->old_gen(); _young_gen = _gens->young_gen(); @@ -176,7 +107,7 @@ new PSAdaptiveSizePolicy(eden_capacity, initial_promo_size, young_gen()->to_space()->capacity_in_bytes(), - intra_heap_alignment(), + _collector_policy->gen_alignment(), max_gc_pause_sec, max_gc_minor_pause_sec, GCTimeRatio diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP +#include "gc_implementation/parallelScavenge/generationSizer.hpp" #include "gc_implementation/parallelScavenge/objectStartArray.hpp" #include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp" #include "gc_implementation/parallelScavenge/psOldGen.hpp" @@ -32,14 +33,12 @@ #include "gc_implementation/shared/gcPolicyCounters.hpp" #include "gc_implementation/shared/gcWhen.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/collectorPolicy.hpp" #include "utilities/ostream.hpp" class AdjoiningGenerations; -class CollectorPolicy; class GCHeapSummary; class GCTaskManager; -class GenerationSizer; -class CollectorPolicy; class PSAdaptiveSizePolicy; class PSHeapSummary; @@ -50,24 +49,20 @@ static PSOldGen* _old_gen; // Sizing policy for entire heap - static PSAdaptiveSizePolicy* _size_policy; - static PSGCAdaptivePolicyCounters* _gc_policy_counters; + static PSAdaptiveSizePolicy* _size_policy; + static PSGCAdaptivePolicyCounters* _gc_policy_counters; static ParallelScavengeHeap* _psh; - size_t _young_gen_alignment; - size_t _old_gen_alignment; - GenerationSizer* _collector_policy; - inline size_t set_alignment(size_t& var, size_t val); - // Collection of generations that are adjacent in the // space reserved for the heap. AdjoiningGenerations* _gens; unsigned int _death_march_count; - static GCTaskManager* _gc_task_manager; // The task manager. + // The task manager + static GCTaskManager* _gc_task_manager; void trace_heap(GCWhen::Type when, GCTracer* tracer); @@ -80,16 +75,7 @@ HeapWord* mem_allocate_old_gen(size_t size); public: - ParallelScavengeHeap() : CollectedHeap() { - _death_march_count = 0; - set_alignment(_young_gen_alignment, intra_heap_alignment()); - set_alignment(_old_gen_alignment, intra_heap_alignment()); - } - - // Return the (conservative) maximum heap alignment - static size_t conservative_max_heap_alignment() { - return intra_heap_alignment(); - } + ParallelScavengeHeap() : CollectedHeap(), _death_march_count(0) { } // For use by VM operations enum CollectionType { @@ -103,8 +89,8 @@ virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; } - static PSYoungGen* young_gen() { return _young_gen; } - static PSOldGen* old_gen() { return _old_gen; } + static PSYoungGen* young_gen() { return _young_gen; } + static PSOldGen* old_gen() { return _old_gen; } virtual PSAdaptiveSizePolicy* size_policy() { return _size_policy; } @@ -121,13 +107,15 @@ void post_initialize(); void update_counters(); - // The alignment used for the various generations. - size_t young_gen_alignment() const { return _young_gen_alignment; } - size_t old_gen_alignment() const { return _old_gen_alignment; } + + // The alignment used for the various areas + size_t space_alignment() { return _collector_policy->space_alignment(); } + size_t generation_alignment() { return _collector_policy->gen_alignment(); } - // The alignment used for eden and survivors within the young gen - // and for boundary between young gen and old gen. - static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; } + // Return the (conservative) maximum heap alignment + static size_t conservative_max_heap_alignment() { + return CollectorPolicy::compute_heap_alignment(); + } size_t capacity() const; size_t used() const; @@ -157,16 +145,15 @@ virtual bool is_in_partial_collection(const void *p); #endif - bool is_in_young(oop p); // reserved part - bool is_in_old(oop p); // reserved part + bool is_in_young(oop p); // reserved part + bool is_in_old(oop p); // reserved part // Memory allocation. "gc_time_limit_was_exceeded" will // be set to true if the adaptive size policy determine that // an excessive amount of time is being spent doing collections // and caused a NULL to be returned. If a NULL is not returned, // "gc_time_limit_was_exceeded" has an undefined meaning. - HeapWord* mem_allocate(size_t size, - bool* gc_overhead_limit_was_exceeded); + HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded); // Allocation attempt(s) during a safepoint. It should never be called // to allocate a new TLAB as this allocation might be satisfied out @@ -257,17 +244,10 @@ // Call these in sequential code around the processing of strong roots. class ParStrongRootsScope : public MarkingCodeBlobClosure::MarkScope { - public: + public: ParStrongRootsScope(); ~ParStrongRootsScope(); }; }; -inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val) -{ - assert(is_power_of_2((intptr_t)val), "must be a power of 2"); - var = round_to(val, intra_heap_alignment()); - return var; -} - #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -37,7 +37,7 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size, - size_t intra_generation_alignment, + size_t space_alignment, double gc_pause_goal_sec, double gc_minor_pause_goal_sec, uint gc_cost_ratio) : @@ -46,9 +46,8 @@ init_survivor_size, gc_pause_goal_sec, gc_cost_ratio), - _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin/ - 100.0), - _intra_generation_alignment(intra_generation_alignment), + _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0), + _space_alignment(space_alignment), _live_at_last_full_gc(init_promo_size), _gc_minor_pause_goal_sec(gc_minor_pause_goal_sec), _latest_major_mutator_interval_seconds(0), @@ -353,11 +352,10 @@ } // Align everything and make a final limit check - const size_t alignment = _intra_generation_alignment; - desired_eden_size = align_size_up(desired_eden_size, alignment); - desired_eden_size = MAX2(desired_eden_size, alignment); + desired_eden_size = align_size_up(desired_eden_size, _space_alignment); + desired_eden_size = MAX2(desired_eden_size, _space_alignment); - eden_limit = align_size_down(eden_limit, alignment); + eden_limit = align_size_down(eden_limit, _space_alignment); // And one last limit check, now that we've aligned things. if (desired_eden_size > eden_limit) { @@ -561,11 +559,10 @@ } // Align everything and make a final limit check - const size_t alignment = _intra_generation_alignment; - desired_promo_size = align_size_up(desired_promo_size, alignment); - desired_promo_size = MAX2(desired_promo_size, alignment); + desired_promo_size = align_size_up(desired_promo_size, _space_alignment); + desired_promo_size = MAX2(desired_promo_size, _space_alignment); - promo_limit = align_size_down(promo_limit, alignment); + promo_limit = align_size_down(promo_limit, _space_alignment); // And one last limit check, now that we've aligned things. desired_promo_size = MIN2(desired_promo_size, promo_limit); @@ -650,7 +647,7 @@ } // If the desired eden size is as small as it will get, // try to adjust the old gen size. - if (*desired_eden_size_ptr <= _intra_generation_alignment) { + if (*desired_eden_size_ptr <= _space_alignment) { // Vary the old gen size to reduce the young gen pause. This // may not be a good idea. This is just a test. if (minor_pause_old_estimator()->decrement_will_decrease()) { @@ -755,7 +752,7 @@ // If the promo size is at the minimum (i.e., the old gen // size will not actually decrease), consider changing the // young gen size. - if (*desired_promo_size_ptr < _intra_generation_alignment) { + if (*desired_promo_size_ptr < _space_alignment) { // If increasing the young generation will decrease the old gen // pause, do it. // During startup there is noise in the statistics for deciding @@ -1066,24 +1063,24 @@ size_t PSAdaptiveSizePolicy::eden_increment_aligned_up(size_t cur_eden) { size_t result = eden_increment(cur_eden, YoungGenerationSizeIncrement); - return align_size_up(result, _intra_generation_alignment); + return align_size_up(result, _space_alignment); } size_t PSAdaptiveSizePolicy::eden_increment_aligned_down(size_t cur_eden) { size_t result = eden_increment(cur_eden); - return align_size_down(result, _intra_generation_alignment); + return align_size_down(result, _space_alignment); } size_t PSAdaptiveSizePolicy::eden_increment_with_supplement_aligned_up( size_t cur_eden) { size_t result = eden_increment(cur_eden, YoungGenerationSizeIncrement + _young_gen_size_increment_supplement); - return align_size_up(result, _intra_generation_alignment); + return align_size_up(result, _space_alignment); } size_t PSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) { size_t eden_heap_delta = eden_decrement(cur_eden); - return align_size_down(eden_heap_delta, _intra_generation_alignment); + return align_size_down(eden_heap_delta, _space_alignment); } size_t PSAdaptiveSizePolicy::eden_decrement(size_t cur_eden) { @@ -1105,24 +1102,24 @@ size_t PSAdaptiveSizePolicy::promo_increment_aligned_up(size_t cur_promo) { size_t result = promo_increment(cur_promo, TenuredGenerationSizeIncrement); - return align_size_up(result, _intra_generation_alignment); + return align_size_up(result, _space_alignment); } size_t PSAdaptiveSizePolicy::promo_increment_aligned_down(size_t cur_promo) { size_t result = promo_increment(cur_promo, TenuredGenerationSizeIncrement); - return align_size_down(result, _intra_generation_alignment); + return align_size_down(result, _space_alignment); } size_t PSAdaptiveSizePolicy::promo_increment_with_supplement_aligned_up( size_t cur_promo) { size_t result = promo_increment(cur_promo, TenuredGenerationSizeIncrement + _old_gen_size_increment_supplement); - return align_size_up(result, _intra_generation_alignment); + return align_size_up(result, _space_alignment); } size_t PSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) { size_t promo_heap_delta = promo_decrement(cur_promo); - return align_size_down(promo_heap_delta, _intra_generation_alignment); + return align_size_down(promo_heap_delta, _space_alignment); } size_t PSAdaptiveSizePolicy::promo_decrement(size_t cur_promo) { @@ -1135,9 +1132,9 @@ bool is_survivor_overflow, uint tenuring_threshold, size_t survivor_limit) { - assert(survivor_limit >= _intra_generation_alignment, + assert(survivor_limit >= _space_alignment, "survivor_limit too small"); - assert((size_t)align_size_down(survivor_limit, _intra_generation_alignment) + assert((size_t)align_size_down(survivor_limit, _space_alignment) == survivor_limit, "survivor_limit not aligned"); // This method is called even if the tenuring threshold and survivor @@ -1201,8 +1198,8 @@ // We're trying to pad the survivor size as little as possible without // overflowing the survivor spaces. size_t target_size = align_size_up((size_t)_avg_survived->padded_average(), - _intra_generation_alignment); - target_size = MAX2(target_size, _intra_generation_alignment); + _space_alignment); + target_size = MAX2(target_size, _space_alignment); if (target_size > survivor_limit) { // Target size is bigger than we can handle. Let's also reduce diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -91,7 +91,7 @@ // for making ergonomic decisions. double _latest_major_mutator_interval_seconds; - const size_t _intra_generation_alignment; // alignment for eden, survivors + const size_t _space_alignment; // alignment for eden, survivors const double _gc_minor_pause_goal_sec; // goal for maximum minor gc pause @@ -229,7 +229,7 @@ PSAdaptiveSizePolicy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size, - size_t intra_generation_alignment, + size_t space_alignment, double gc_pause_goal_sec, double gc_minor_pause_goal_sec, uint gc_time_ratio); @@ -378,7 +378,7 @@ // remain almost full anyway (top() will be near end(), but there will be a // large filler object at the bottom). const size_t sz = gen_size / MinSurvivorRatio; - const size_t alignment = _intra_generation_alignment; + const size_t alignment = _space_alignment; return sz > alignment ? align_size_down(sz, alignment) : alignment; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -103,7 +103,7 @@ // Compute maximum space sizes for performance counters ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - size_t alignment = heap->intra_heap_alignment(); + size_t alignment = heap->space_alignment(); size_t size = virtual_space()->reserved_size(); size_t max_survivor_size; @@ -156,8 +156,9 @@ assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); // Compute sizes - size_t alignment = heap->intra_heap_alignment(); + size_t alignment = heap->space_alignment(); size_t size = virtual_space()->committed_size(); + assert(size >= 3 * alignment, "Young space is not large enough for eden + 2 survivors"); size_t survivor_size = size / InitialSurvivorRatio; survivor_size = align_size_down(survivor_size, alignment); @@ -207,7 +208,7 @@ #ifndef PRODUCT void PSYoungGen::space_invariants() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t alignment = heap->intra_heap_alignment(); + const size_t alignment = heap->space_alignment(); // Currently, our eden size cannot shrink to zero guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small"); @@ -491,7 +492,7 @@ char* to_end = (char*)to_space()->end(); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t alignment = heap->intra_heap_alignment(); + const size_t alignment = heap->space_alignment(); const bool maintain_minimum = (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); @@ -840,8 +841,8 @@ size_t PSYoungGen::available_to_live() { size_t delta_in_survivor = 0; ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - const size_t space_alignment = heap->intra_heap_alignment(); - const size_t gen_alignment = heap->young_gen_alignment(); + const size_t space_alignment = heap->space_alignment(); + const size_t gen_alignment = heap->generation_alignment(); MutableSpace* space_shrinking = NULL; if (from_space()->end() > to_space()->end()) { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -469,6 +469,10 @@ fill_with_object_impl(start, words, zap); } +void CollectedHeap::post_initialize() { + collector_policy()->post_heap_initialize(); +} + HeapWord* CollectedHeap::allocate_new_tlab(size_t size) { guarantee(false, "thread-local allocation buffers not supported"); return NULL; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/abstractInterpreter.hpp --- a/src/share/vm/interpreter/abstractInterpreter.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -158,8 +158,8 @@ // Runtime support // length = invoke bytecode length (to advance to next bytecode) - static address deopt_entry (TosState state, int length) { ShouldNotReachHere(); return NULL; } - static address return_entry (TosState state, int length) { ShouldNotReachHere(); return NULL; } + static address deopt_entry(TosState state, int length) { ShouldNotReachHere(); return NULL; } + static address return_entry(TosState state, int length, Bytecodes::Code code) { ShouldNotReachHere(); return NULL; } static address rethrow_exception_entry() { return _rethrow_exception_entry; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/cppInterpreter.hpp --- a/src/share/vm/interpreter/cppInterpreter.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/cppInterpreter.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -78,7 +78,7 @@ static address stack_result_to_stack(int index) { return _stack_to_stack[index]; } static address stack_result_to_native(int index) { return _stack_to_native_abi[index]; } - static address return_entry (TosState state, int length); + static address return_entry (TosState state, int length, Bytecodes::Code code); static address deopt_entry (TosState state, int length); #ifdef TARGET_ARCH_x86 diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/interpreter.cpp --- a/src/share/vm/interpreter/interpreter.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/interpreter.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -329,15 +329,21 @@ //------------------------------------------------------------------------------------------------------------------------ // Deoptimization support -// If deoptimization happens, this function returns the point of next bytecode to continue execution +/** + * If a deoptimization happens, this function returns the point of next bytecode to continue execution. + */ address AbstractInterpreter::deopt_continue_after_entry(Method* method, address bcp, int callee_parameters, bool is_top_frame) { assert(method->contains(bcp), "just checkin'"); - Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); + + // Get the original and rewritten bytecode. + Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); assert(!Interpreter::bytecode_should_reexecute(code), "should not reexecute"); - int bci = method->bci_from(bcp); - int length = -1; // initial value for debugging + + const int bci = method->bci_from(bcp); + // compute continuation length - length = Bytecodes::length_at(method, bcp); + const int length = Bytecodes::length_at(method, bcp); + // compute result type BasicType type = T_ILLEGAL; @@ -393,7 +399,7 @@ return is_top_frame ? Interpreter::deopt_entry (as_TosState(type), length) - : Interpreter::return_entry(as_TosState(type), length); + : Interpreter::return_entry(as_TosState(type), length, code); } // If deoptimization happens, this function returns the point where the interpreter reexecutes diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -152,11 +152,13 @@ // Could be an Object method inherited into an interface, but still a vtable call. kind = CallInfo::vtable_call; } else if (!resolved_klass->is_interface()) { - // A miranda method. Compute the vtable index. + // A default or miranda method. Compute the vtable index. ResourceMark rm; klassVtable* vt = InstanceKlass::cast(resolved_klass)->vtable(); - index = vt->index_of_miranda(resolved_method->name(), - resolved_method->signature()); + index = LinkResolver::vtable_index_of_interface_method(resolved_klass, + resolved_method); + assert(index >= 0 , "we should have valid vtable index at this point"); + kind = CallInfo::vtable_call; } else if (resolved_method->has_vtable_index()) { // Can occur if an interface redeclares a method of Object. @@ -279,7 +281,7 @@ } int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, - methodHandle resolved_method, TRAPS) { + methodHandle resolved_method) { int vtable_index = Method::invalid_vtable_index; Symbol* name = resolved_method->name(); @@ -295,7 +297,7 @@ } if (vtable_index == Method::invalid_vtable_index) { // get vtable_index for miranda methods - ResourceMark rm(THREAD); + ResourceMark rm; klassVtable *vt = InstanceKlass::cast(klass())->vtable(); vtable_index = vt->index_of_miranda(name, signature); } @@ -691,7 +693,7 @@ ); resolved_method->access_flags().print_on(tty); if (resolved_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (resolved_method->is_overpass()) { tty->print("overpass"); @@ -937,7 +939,7 @@ ); resolved_method->access_flags().print_on(tty); if (resolved_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (resolved_method->is_overpass()) { tty->print("overpass"); @@ -1017,7 +1019,7 @@ ); sel_method->access_flags().print_on(tty); if (sel_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (sel_method->is_overpass()) { tty->print("overpass"); @@ -1081,7 +1083,7 @@ ); resolved_method->access_flags().print_on(tty); if (resolved_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (resolved_method->is_overpass()) { tty->print("overpass"); @@ -1118,7 +1120,7 @@ // do lookup based on receiver klass using the vtable index if (resolved_method->method_holder()->is_interface()) { // miranda method vtable_index = vtable_index_of_interface_method(resolved_klass, - resolved_method, CHECK); + resolved_method); assert(vtable_index >= 0 , "we should have valid vtable index at this point"); InstanceKlass* inst = InstanceKlass::cast(recv_klass()); @@ -1175,7 +1177,7 @@ ); selected_method->access_flags().print_on(tty); if (selected_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (selected_method->is_overpass()) { tty->print("overpass"); @@ -1268,14 +1270,6 @@ sel_method->name(), sel_method->signature())); } - // setup result - if (!resolved_method->has_itable_index()) { - int vtable_index = resolved_method->vtable_index(); - assert(vtable_index == sel_method->vtable_index(), "sanity check"); - result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); - return; - } - int itable_index = resolved_method()->itable_index(); if (TraceItables && Verbose) { ResourceMark rm(THREAD); @@ -1289,14 +1283,22 @@ ); sel_method->access_flags().print_on(tty); if (sel_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (sel_method->is_overpass()) { tty->print("overpass"); } tty->cr(); } - result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); + // setup result + if (!resolved_method->has_itable_index()) { + int vtable_index = resolved_method->vtable_index(); + assert(vtable_index == sel_method->vtable_index(), "sanity check"); + result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); + } else { + int itable_index = resolved_method()->itable_index(); + result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); + } } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/linkResolver.hpp --- a/src/share/vm/interpreter/linkResolver.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/linkResolver.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -130,7 +130,6 @@ static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS); - static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method, TRAPS); static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); @@ -186,6 +185,7 @@ static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); + static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method); // same as above for compile-time resolution; returns vtable_index if current_klass if linked static int resolve_virtual_vtable_index (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/rewriter.cpp --- a/src/share/vm/interpreter/rewriter.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/rewriter.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -72,19 +72,21 @@ // Unrewrite the bytecodes if an error occurs. void Rewriter::restore_bytecodes() { int len = _methods->length(); + bool invokespecial_error = false; for (int i = len-1; i >= 0; i--) { Method* method = _methods->at(i); - scan_method(method, true); + scan_method(method, true, &invokespecial_error); + assert(!invokespecial_error, "reversing should not get an invokespecial error"); } } // Creates a constant pool cache given a CPC map void Rewriter::make_constant_pool_cache(TRAPS) { - const int length = _cp_cache_map.length(); ClassLoaderData* loader_data = _pool->pool_holder()->class_loader_data(); ConstantPoolCache* cache = - ConstantPoolCache::allocate(loader_data, length, _cp_cache_map, + ConstantPoolCache::allocate(loader_data, _cp_cache_map, + _invokedynamic_cp_cache_map, _invokedynamic_references_map, CHECK); // initialize object cache in constant pool @@ -154,6 +156,30 @@ } } +// If the constant pool entry for invokespecial is InterfaceMethodref, +// we need to add a separate cpCache entry for its resolution, because it is +// different than the resolution for invokeinterface with InterfaceMethodref. +// These cannot share cpCache entries. It's unclear if all invokespecial to +// InterfaceMethodrefs would resolve to the same thing so a new cpCache entry +// is created for each one. This was added with lambda. +void Rewriter::rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error) { + address p = bcp + offset; + if (!reverse) { + int cp_index = Bytes::get_Java_u2(p); + if (_pool->tag_at(cp_index).is_interface_method()) { + int cache_index = add_invokespecial_cp_cache_entry(cp_index); + if (cache_index != (int)(jushort) cache_index) { + *invokespecial_error = true; + } + Bytes::put_native_u2(p, cache_index); + } else { + rewrite_member_reference(bcp, offset, reverse); + } + } else { + rewrite_member_reference(bcp, offset, reverse); + } +} + // Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse) { @@ -203,7 +229,7 @@ if (!reverse) { int cp_index = Bytes::get_Java_u2(p); int cache_index = add_invokedynamic_cp_cache_entry(cp_index); - add_invokedynamic_resolved_references_entries(cp_index, cache_index); + int resolved_index = add_invokedynamic_resolved_references_entries(cp_index, cache_index); // Replace the trailing four bytes with a CPC index for the dynamic // call site. Unlike other CPC entries, there is one per bytecode, // not just one per distinct CP entry. In other words, the @@ -212,13 +238,20 @@ // all these entries. That is the main reason invokedynamic // must have a five-byte instruction format. (Of course, other JVM // implementations can use the bytes for other purposes.) + // Note: We use native_u4 format exclusively for 4-byte indexes. Bytes::put_native_u4(p, ConstantPool::encode_invokedynamic_index(cache_index)); - // Note: We use native_u4 format exclusively for 4-byte indexes. + // add the bcp in case we need to patch this bytecode if we also find a + // invokespecial/InterfaceMethodref in the bytecode stream + _patch_invokedynamic_bcps->push(p); + _patch_invokedynamic_refs->push(resolved_index); } else { - // callsite index int cache_index = ConstantPool::decode_invokedynamic_index( Bytes::get_native_u4(p)); - int cp_index = cp_cache_entry_pool_index(cache_index); + // 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); assert(_pool->tag_at(cp_index).is_invoke_dynamic(), "wrong index"); // zero out 4 bytes Bytes::put_Java_u4(p, 0); @@ -226,6 +259,34 @@ } } +void Rewriter::patch_invokedynamic_bytecodes() { + // If the end of the cp_cache is the same as after initializing with the + // cpool, nothing needs to be done. Invokedynamic bytecodes are at the + // correct offsets. ie. no invokespecials added + int delta = cp_cache_delta(); + if (delta > 0) { + int length = _patch_invokedynamic_bcps->length(); + assert(length == _patch_invokedynamic_refs->length(), + "lengths should match"); + for (int i = 0; i < length; i++) { + address p = _patch_invokedynamic_bcps->at(i); + int cache_index = ConstantPool::decode_invokedynamic_index( + Bytes::get_native_u4(p)); + Bytes::put_native_u4(p, ConstantPool::encode_invokedynamic_index(cache_index + delta)); + + // invokedynamic resolved references map also points to cp cache and must + // add delta to each. + int resolved_index = _patch_invokedynamic_refs->at(i); + for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) { + assert(_invokedynamic_references_map[resolved_index+entry] == cache_index, + "should be the same index"); + _invokedynamic_references_map.at_put(resolved_index+entry, + cache_index + delta); + } + } + } +} + // Rewrite some ldc bytecodes to _fast_aldc void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide, @@ -269,7 +330,7 @@ // Rewrites a method given the index_map information -void Rewriter::scan_method(Method* method, bool reverse) { +void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_error) { int nof_jsrs = 0; bool has_monitor_bytecodes = false; @@ -329,12 +390,17 @@ #endif break; } + + case Bytecodes::_invokespecial : { + rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error); + break; + } + case Bytecodes::_getstatic : // fall through case Bytecodes::_putstatic : // fall through case Bytecodes::_getfield : // fall through case Bytecodes::_putfield : // fall through case Bytecodes::_invokevirtual : // fall through - case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : case Bytecodes::_invokeinterface: case Bytecodes::_invokehandle : // if reverse=true @@ -423,12 +489,26 @@ // rewrite methods, in two passes int len = _methods->length(); + bool invokespecial_error = false; for (int i = len-1; i >= 0; i--) { Method* method = _methods->at(i); - scan_method(method); + scan_method(method, false, &invokespecial_error); + if (invokespecial_error) { + // If you get an error here, there is no reversing bytecodes + // This exception is stored for this class and no further attempt is + // made at verifying or rewriting. + THROW_MSG(vmSymbols::java_lang_InternalError(), + "This classfile overflows invokespecial for interfaces " + "and cannot be loaded"); + return; + } } + // May have to fix invokedynamic bytecodes if invokestatic/InterfaceMethodref + // entries had to be added. + patch_invokedynamic_bytecodes(); + // allocate constant pool cache, now that we've seen all the bytecodes make_constant_pool_cache(THREAD); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/rewriter.hpp --- a/src/share/vm/interpreter/rewriter.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/rewriter.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -46,55 +46,102 @@ intArray _method_handle_invokers; int _resolved_reference_limit; + // For mapping invokedynamic bytecodes, which are discovered during method + // scanning. The invokedynamic entries are added at the end of the cpCache. + // If there are any invokespecial/InterfaceMethodref special case bytecodes, + // these entries are added before invokedynamic entries so that the + // invokespecial bytecode 16 bit index doesn't overflow. + intStack _invokedynamic_cp_cache_map; + + // For patching. + GrowableArray
* _patch_invokedynamic_bcps; + GrowableArray* _patch_invokedynamic_refs; + void init_maps(int length) { _cp_map.initialize(length, -1); // Choose an initial value large enough that we don't get frequent // calls to grow(). - _cp_cache_map.initialize(length / 2); + _cp_cache_map.initialize(length/2); // Also cache resolved objects, in another different cache. _reference_map.initialize(length, -1); - _resolved_references_map.initialize(length / 2); - _invokedynamic_references_map.initialize(length / 2); + _resolved_references_map.initialize(length/2); + _invokedynamic_references_map.initialize(length/2); _resolved_reference_limit = -1; - DEBUG_ONLY(_cp_cache_index_limit = -1); + _first_iteration_cp_cache_limit = -1; + + // invokedynamic specific fields + _invokedynamic_cp_cache_map.initialize(length/4); + _patch_invokedynamic_bcps = new GrowableArray
(length/4); + _patch_invokedynamic_refs = new GrowableArray(length/4); } - int _cp_cache_index_limit; + int _first_iteration_cp_cache_limit; void record_map_limits() { -#ifdef ASSERT - // Record initial size of the two arrays generated for the CP cache: - _cp_cache_index_limit = _cp_cache_map.length(); -#endif //ASSERT + // Record initial size of the two arrays generated for the CP cache + // relative to walking the constant pool. + _first_iteration_cp_cache_limit = _cp_cache_map.length(); _resolved_reference_limit = _resolved_references_map.length(); } + int cp_cache_delta() { + // How many cp cache entries were added since recording map limits after + // cp cache initialization? + assert(_first_iteration_cp_cache_limit != -1, "only valid after first iteration"); + return _cp_cache_map.length() - _first_iteration_cp_cache_limit; + } + int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; } bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; } + int add_map_entry(int cp_index, intArray* cp_map, intStack* cp_cache_map) { + assert(cp_map->at(cp_index) == -1, "not twice on same cp_index"); + int cache_index = cp_cache_map->append(cp_index); + cp_map->at_put(cp_index, cache_index); + return cache_index; + } + int add_cp_cache_entry(int cp_index) { assert(_pool->tag_at(cp_index).value() != JVM_CONSTANT_InvokeDynamic, "use indy version"); - assert(_cp_map[cp_index] == -1, "not twice on same cp_index"); - assert(_cp_cache_index_limit == -1, "do not add cache entries after first iteration"); - int cache_index = _cp_cache_map.append(cp_index); - _cp_map.at_put(cp_index, cache_index); + assert(_first_iteration_cp_cache_limit == -1, "do not add cache entries after first iteration"); + int cache_index = add_map_entry(cp_index, &_cp_map, &_cp_cache_map); assert(cp_entry_to_cp_cache(cp_index) == cache_index, ""); assert(cp_cache_entry_pool_index(cache_index) == cp_index, ""); return cache_index; } - // add a new CP cache entry beyond the normal cache (for invokedynamic only) int add_invokedynamic_cp_cache_entry(int cp_index) { assert(_pool->tag_at(cp_index).value() == JVM_CONSTANT_InvokeDynamic, "use non-indy version"); - assert(_cp_map[cp_index] == -1, "do not map from cp_index"); - assert(_cp_cache_index_limit >= 0, "add indy cache entries after first iteration"); + assert(_first_iteration_cp_cache_limit >= 0, "add indy cache entries after first iteration"); + // add to the invokedynamic index map. + int cache_index = _invokedynamic_cp_cache_map.append(cp_index); + // do not update _cp_map, since the mapping is one-to-many + assert(invokedynamic_cp_cache_entry_pool_index(cache_index) == cp_index, ""); + // this index starts at one but in the bytecode it's appended to the end. + return cache_index + _first_iteration_cp_cache_limit; + } + + int invokedynamic_cp_cache_entry_pool_index(int cache_index) { + int cp_index = _invokedynamic_cp_cache_map[cache_index]; + return cp_index; + } + + // add a new CP cache entry beyond the normal cache for the special case of + // invokespecial with InterfaceMethodref as cpool operand. + int add_invokespecial_cp_cache_entry(int cp_index) { + assert(_first_iteration_cp_cache_limit >= 0, "add these special cache entries after first iteration"); + // Don't add InterfaceMethodref if it already exists at the end. + for (int i = _first_iteration_cp_cache_limit; i < _cp_cache_map.length(); i++) { + if (cp_cache_entry_pool_index(i) == cp_index) { + return i; + } + } int cache_index = _cp_cache_map.append(cp_index); - assert(cache_index >= _cp_cache_index_limit, ""); + assert(cache_index >= _first_iteration_cp_cache_limit, ""); // do not update _cp_map, since the mapping is one-to-many assert(cp_cache_entry_pool_index(cache_index) == cp_index, ""); return cache_index; } - // fix duplicated code later int cp_entry_to_resolved_references(int cp_index) const { assert(has_entry_in_resolved_references(cp_index), "oob"); return _reference_map[cp_index]; @@ -105,10 +152,7 @@ // add a new entry to the resolved_references map int add_resolved_references_entry(int cp_index) { - assert(_reference_map[cp_index] == -1, "not twice on same cp_index"); - assert(_resolved_reference_limit == -1, "do not add CP refs after first iteration"); - int ref_index = _resolved_references_map.append(cp_index); - _reference_map.at_put(cp_index, ref_index); + int ref_index = add_map_entry(cp_index, &_reference_map, &_resolved_references_map); assert(cp_entry_to_resolved_references(cp_index) == ref_index, ""); return ref_index; } @@ -137,7 +181,7 @@ // Access the contents of _cp_cache_map to determine CP cache layout. int cp_cache_entry_pool_index(int cache_index) { int cp_index = _cp_cache_map[cache_index]; - return cp_index; + return cp_index; } // All the work goes in here: @@ -145,12 +189,16 @@ void compute_index_maps(); void make_constant_pool_cache(TRAPS); - void scan_method(Method* m, bool reverse = false); + void scan_method(Method* m, bool reverse, bool* invokespecial_error); void rewrite_Object_init(methodHandle m, TRAPS); - void rewrite_member_reference(address bcp, int offset, bool reverse = false); - void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse = false); - void rewrite_invokedynamic(address bcp, int offset, bool reverse = false); - void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse = false); + void rewrite_member_reference(address bcp, int offset, bool reverse); + void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse); + void rewrite_invokedynamic(address bcp, int offset, bool reverse); + void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse); + void rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error); + + void patch_invokedynamic_bytecodes(); + // Revert bytecodes in case of an exception. void restore_bytecodes(); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -184,8 +184,9 @@ EntryPoint TemplateInterpreter::_continuation_entry; EntryPoint TemplateInterpreter::_safept_entry; -address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; -address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; +address TemplateInterpreter::_invoke_return_entry[TemplateInterpreter::number_of_return_addrs]; +address TemplateInterpreter::_invokeinterface_return_entry[TemplateInterpreter::number_of_return_addrs]; +address TemplateInterpreter::_invokedynamic_return_entry[TemplateInterpreter::number_of_return_addrs]; DispatchTable TemplateInterpreter::_active_table; DispatchTable TemplateInterpreter::_normal_table; @@ -237,22 +238,37 @@ #endif // !PRODUCT { CodeletMark cm(_masm, "return entry points"); + const int index_size = sizeof(u2); for (int i = 0; i < Interpreter::number_of_return_entries; i++) { Interpreter::_return_entry[i] = EntryPoint( - generate_return_entry_for(itos, i), - generate_return_entry_for(itos, i), - generate_return_entry_for(itos, i), - generate_return_entry_for(atos, i), - generate_return_entry_for(itos, i), - generate_return_entry_for(ltos, i), - generate_return_entry_for(ftos, i), - generate_return_entry_for(dtos, i), - generate_return_entry_for(vtos, i) + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(atos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(ltos, i, index_size), + generate_return_entry_for(ftos, i, index_size), + generate_return_entry_for(dtos, i, index_size), + generate_return_entry_for(vtos, i, index_size) ); } } + { CodeletMark cm(_masm, "invoke return entry points"); + const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); + const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); + const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); + + for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { + TosState state = states[i]; + Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); + Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); + Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); + } + } + { CodeletMark cm(_masm, "earlyret entry points"); Interpreter::_earlyret_entry = EntryPoint( @@ -298,13 +314,6 @@ } } - for (int j = 0; j < number_of_states; j++) { - const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos}; - int index = Interpreter::TosState_as_index(states[j]); - Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); - Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); - } - { CodeletMark cm(_masm, "continuation entry points"); Interpreter::_continuation_entry = EntryPoint( @@ -534,9 +543,46 @@ //------------------------------------------------------------------------------------------------------------------------ // Entry points -address TemplateInterpreter::return_entry(TosState state, int length) { +/** + * Returns the return entry table for the given invoke bytecode. + */ +address* TemplateInterpreter::invoke_return_entry_table_for(Bytecodes::Code code) { + switch (code) { + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokehandle: + return Interpreter::invoke_return_entry_table(); + case Bytecodes::_invokeinterface: + return Interpreter::invokeinterface_return_entry_table(); + case Bytecodes::_invokedynamic: + return Interpreter::invokedynamic_return_entry_table(); + default: + fatal(err_msg("invalid bytecode: %s", Bytecodes::name(code))); + return NULL; + } +} + +/** + * Returns the return entry address for the given top-of-stack state and bytecode. + */ +address TemplateInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length"); - return _return_entry[length].entry(state); + const int index = TosState_as_index(state); + switch (code) { + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + case Bytecodes::_invokehandle: + return _invoke_return_entry[index]; + case Bytecodes::_invokeinterface: + return _invokeinterface_return_entry[index]; + case Bytecodes::_invokedynamic: + return _invokedynamic_return_entry[index]; + default: + assert(!Bytecodes::is_invoke(code), err_msg("invoke instructions should be handled separately: %s", Bytecodes::name(code))); + return _return_entry[length].entry(state); + } } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/templateInterpreter.hpp --- a/src/share/vm/interpreter/templateInterpreter.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/templateInterpreter.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -120,8 +120,9 @@ static EntryPoint _continuation_entry; static EntryPoint _safept_entry; - static address _return_3_addrs_by_index[number_of_return_addrs]; // for invokevirtual return entries - static address _return_5_addrs_by_index[number_of_return_addrs]; // for invokeinterface return entries + static address _invoke_return_entry[number_of_return_addrs]; // for invokestatic, invokespecial, invokevirtual return entries + static address _invokeinterface_return_entry[number_of_return_addrs]; // for invokeinterface return entries + static address _invokedynamic_return_entry[number_of_return_addrs]; // for invokedynamic return entries static DispatchTable _active_table; // the active dispatch table (used by the interpreter for dispatch) static DispatchTable _normal_table; // the normal dispatch table (used to set the active table in normal mode) @@ -161,12 +162,15 @@ static address* normal_table() { return _normal_table.table_for(); } // Support for invokes - static address* return_3_addrs_by_index_table() { return _return_3_addrs_by_index; } - static address* return_5_addrs_by_index_table() { return _return_5_addrs_by_index; } - static int TosState_as_index(TosState state); // computes index into return_3_entry_by_index table + static address* invoke_return_entry_table() { return _invoke_return_entry; } + static address* invokeinterface_return_entry_table() { return _invokeinterface_return_entry; } + static address* invokedynamic_return_entry_table() { return _invokedynamic_return_entry; } + static int TosState_as_index(TosState state); - static address return_entry (TosState state, int length); - static address deopt_entry (TosState state, int length); + static address* invoke_return_entry_table_for(Bytecodes::Code code); + + static address deopt_entry(TosState state, int length); + static address return_entry(TosState state, int length, Bytecodes::Code code); // Safepoint support static void notice_safepoints(); // stops the thread when reaching a safepoint diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/interpreter/templateInterpreterGenerator.hpp --- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -53,7 +53,7 @@ address generate_ClassCastException_handler(); address generate_ArrayIndexOutOfBounds_handler(const char* name); address generate_continuation_for(TosState state); - address generate_return_entry_for(TosState state, int step); + address generate_return_entry_for(TosState state, int step, size_t index_size); address generate_earlyret_entry_for(TosState state); address generate_deopt_entry_for(TosState state, int step); address generate_safept_entry_for(TosState state, address runtime_entry); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/collectorPolicy.cpp --- a/src/share/vm/memory/collectorPolicy.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/collectorPolicy.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -47,54 +47,107 @@ // CollectorPolicy methods. +CollectorPolicy::CollectorPolicy() : + _space_alignment(0), + _heap_alignment(0), + _initial_heap_byte_size(InitialHeapSize), + _max_heap_byte_size(MaxHeapSize), + _min_heap_byte_size(Arguments::min_heap_size()), + _max_heap_size_cmdline(false), + _size_policy(NULL), + _should_clear_all_soft_refs(false), + _all_soft_refs_clear(false) +{} + +#ifdef ASSERT +void CollectorPolicy::assert_flags() { + assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes"); + assert(InitialHeapSize % _heap_alignment == 0, "InitialHeapSize alignment"); + assert(MaxHeapSize % _heap_alignment == 0, "MaxHeapSize alignment"); +} + +void CollectorPolicy::assert_size_info() { + assert(InitialHeapSize == _initial_heap_byte_size, "Discrepancy between InitialHeapSize flag and local storage"); + assert(MaxHeapSize == _max_heap_byte_size, "Discrepancy between MaxHeapSize flag and local storage"); + assert(_max_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible minimum and maximum heap sizes"); + assert(_initial_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible initial and minimum heap sizes"); + assert(_max_heap_byte_size >= _initial_heap_byte_size, "Ergonomics decided on incompatible initial and maximum heap sizes"); + assert(_min_heap_byte_size % _heap_alignment == 0, "min_heap_byte_size alignment"); + assert(_initial_heap_byte_size % _heap_alignment == 0, "initial_heap_byte_size alignment"); + assert(_max_heap_byte_size % _heap_alignment == 0, "max_heap_byte_size alignment"); +} +#endif // ASSERT + void CollectorPolicy::initialize_flags() { - assert(_max_alignment >= _min_alignment, - err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT, - _max_alignment, _min_alignment)); - assert(_max_alignment % _min_alignment == 0, - err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT, - _max_alignment, _min_alignment)); + assert(_space_alignment != 0, "Space alignment not set up properly"); + assert(_heap_alignment != 0, "Heap alignment not set up properly"); + assert(_heap_alignment >= _space_alignment, + err_msg("heap_alignment: " SIZE_FORMAT " less than space_alignment: " SIZE_FORMAT, + _heap_alignment, _space_alignment)); + assert(_heap_alignment % _space_alignment == 0, + err_msg("heap_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT, + _heap_alignment, _space_alignment)); - if (MaxHeapSize < InitialHeapSize) { - vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); + if (FLAG_IS_CMDLINE(MaxHeapSize)) { + if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) { + vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size"); + } + if (_min_heap_byte_size != 0 && MaxHeapSize < _min_heap_byte_size) { + vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified"); + } + _max_heap_size_cmdline = true; } - MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, _min_alignment); + // Check heap parameter properties + if (InitialHeapSize < M) { + vm_exit_during_initialization("Too small initial heap"); + } + if (_min_heap_byte_size < M) { + vm_exit_during_initialization("Too small minimum heap"); + } + + // User inputs from -Xmx and -Xms must be aligned + _min_heap_byte_size = align_size_up(_min_heap_byte_size, _heap_alignment); + uintx aligned_initial_heap_size = align_size_up(InitialHeapSize, _heap_alignment); + uintx aligned_max_heap_size = align_size_up(MaxHeapSize, _heap_alignment); + + // Write back to flags if the values changed + if (aligned_initial_heap_size != InitialHeapSize) { + FLAG_SET_ERGO(uintx, InitialHeapSize, aligned_initial_heap_size); + } + if (aligned_max_heap_size != MaxHeapSize) { + FLAG_SET_ERGO(uintx, MaxHeapSize, aligned_max_heap_size); + } + + if (FLAG_IS_CMDLINE(InitialHeapSize) && _min_heap_byte_size != 0 && + InitialHeapSize < _min_heap_byte_size) { + vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified"); + } + if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) { + FLAG_SET_ERGO(uintx, MaxHeapSize, InitialHeapSize); + } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) { + FLAG_SET_ERGO(uintx, InitialHeapSize, MaxHeapSize); + if (InitialHeapSize < _min_heap_byte_size) { + _min_heap_byte_size = InitialHeapSize; + } + } + + _initial_heap_byte_size = InitialHeapSize; + _max_heap_byte_size = MaxHeapSize; + + FLAG_SET_ERGO(uintx, MinHeapDeltaBytes, align_size_up(MinHeapDeltaBytes, _space_alignment)); + + DEBUG_ONLY(CollectorPolicy::assert_flags();) } void CollectorPolicy::initialize_size_info() { - // User inputs from -mx and ms must be aligned - _min_heap_byte_size = align_size_up(Arguments::min_heap_size(), _min_alignment); - _initial_heap_byte_size = align_size_up(InitialHeapSize, _min_alignment); - _max_heap_byte_size = align_size_up(MaxHeapSize, _max_alignment); - - // Check heap parameter properties - if (_initial_heap_byte_size < M) { - vm_exit_during_initialization("Too small initial heap"); - } - // Check heap parameter properties - if (_min_heap_byte_size < M) { - vm_exit_during_initialization("Too small minimum heap"); - } - if (_initial_heap_byte_size <= NewSize) { - // make sure there is at least some room in old space - vm_exit_during_initialization("Too small initial heap for new size specified"); - } - if (_max_heap_byte_size < _min_heap_byte_size) { - vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified"); - } - if (_initial_heap_byte_size < _min_heap_byte_size) { - vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified"); - } - if (_max_heap_byte_size < _initial_heap_byte_size) { - vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); - } - if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " Maximum heap " SIZE_FORMAT, _min_heap_byte_size, _initial_heap_byte_size, _max_heap_byte_size); } + + DEBUG_ONLY(CollectorPolicy::assert_size_info();) } bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) { @@ -105,7 +158,6 @@ GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap, int max_covered_regions) { - assert(rem_set_name() == GenRemSet::CardTable, "unrecognized GenRemSet::Name"); return new CardTableRS(whole_heap, max_covered_regions); } @@ -119,7 +171,7 @@ _all_soft_refs_clear = true; } -size_t CollectorPolicy::compute_max_alignment() { +size_t CollectorPolicy::compute_heap_alignment() { // The card marking array and the offset arrays for old generations are // committed in os pages as well. Make sure they are entirely full (to // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 @@ -146,18 +198,21 @@ // GenCollectorPolicy methods. +GenCollectorPolicy::GenCollectorPolicy() : + _min_gen0_size(0), + _initial_gen0_size(0), + _max_gen0_size(0), + _gen_alignment(0), + _generations(NULL) +{} + size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) { - size_t x = base_size / (NewRatio+1); - size_t new_gen_size = x > _min_alignment ? - align_size_down(x, _min_alignment) : - _min_alignment; - return new_gen_size; + return align_size_down_bounded(base_size / (NewRatio + 1), _gen_alignment); } size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size, size_t maximum_size) { - size_t alignment = _min_alignment; - size_t max_minus = maximum_size - alignment; + size_t max_minus = maximum_size - _gen_alignment; return desired_size < max_minus ? desired_size : max_minus; } @@ -165,7 +220,7 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size) { - const double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0; + const double max_gc_pause_sec = ((double) MaxGCPauseMillis) / 1000.0; _size_policy = new AdaptiveSizePolicy(init_eden_size, init_promo_size, init_survivor_size, @@ -173,100 +228,181 @@ GCTimeRatio); } +size_t GenCollectorPolicy::young_gen_size_lower_bound() { + // The young generation must be aligned and have room for eden + two survivors + return align_size_up(3 * _space_alignment, _gen_alignment); +} + +#ifdef ASSERT +void GenCollectorPolicy::assert_flags() { + CollectorPolicy::assert_flags(); + assert(NewSize >= _min_gen0_size, "Ergonomics decided on a too small young gen size"); + assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes"); + assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes"); + assert(NewSize % _gen_alignment == 0, "NewSize alignment"); + assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % _gen_alignment == 0, "MaxNewSize alignment"); +} + +void TwoGenerationCollectorPolicy::assert_flags() { + GenCollectorPolicy::assert_flags(); + assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes"); + assert(OldSize % _gen_alignment == 0, "OldSize alignment"); +} + +void GenCollectorPolicy::assert_size_info() { + CollectorPolicy::assert_size_info(); + // GenCollectorPolicy::initialize_size_info may update the MaxNewSize + assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes"); + assert(NewSize == _initial_gen0_size, "Discrepancy between NewSize flag and local storage"); + assert(MaxNewSize == _max_gen0_size, "Discrepancy between MaxNewSize flag and local storage"); + assert(_min_gen0_size <= _initial_gen0_size, "Ergonomics decided on incompatible minimum and initial young gen sizes"); + assert(_initial_gen0_size <= _max_gen0_size, "Ergonomics decided on incompatible initial and maximum young gen sizes"); + assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment"); + assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment"); + assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment"); +} + +void TwoGenerationCollectorPolicy::assert_size_info() { + GenCollectorPolicy::assert_size_info(); + assert(OldSize == _initial_gen1_size, "Discrepancy between OldSize flag and local storage"); + assert(_min_gen1_size <= _initial_gen1_size, "Ergonomics decided on incompatible minimum and initial old gen sizes"); + assert(_initial_gen1_size <= _max_gen1_size, "Ergonomics decided on incompatible initial and maximum old gen sizes"); + assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment"); + assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment"); + assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes"); +} +#endif // ASSERT + void GenCollectorPolicy::initialize_flags() { - // All sizes must be multiples of the generation granularity. - _min_alignment = (uintx) Generation::GenGrain; - _max_alignment = compute_max_alignment(); - CollectorPolicy::initialize_flags(); - // All generational heaps have a youngest gen; handle those flags here. + assert(_gen_alignment != 0, "Generation alignment not set up properly"); + assert(_heap_alignment >= _gen_alignment, + err_msg("heap_alignment: " SIZE_FORMAT " less than gen_alignment: " SIZE_FORMAT, + _heap_alignment, _gen_alignment)); + assert(_gen_alignment % _space_alignment == 0, + err_msg("gen_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT, + _gen_alignment, _space_alignment)); + assert(_heap_alignment % _gen_alignment == 0, + err_msg("heap_alignment: " SIZE_FORMAT " not aligned by gen_alignment: " SIZE_FORMAT, + _heap_alignment, _gen_alignment)); + + // All generational heaps have a youngest gen; handle those flags here - // Adjust max size parameters - if (NewSize > MaxNewSize) { - MaxNewSize = NewSize; + // Make sure the heap is large enough for two generations + uintx smallest_new_size = young_gen_size_lower_bound(); + uintx smallest_heap_size = align_size_up(smallest_new_size + align_size_up(_space_alignment, _gen_alignment), + _heap_alignment); + if (MaxHeapSize < smallest_heap_size) { + FLAG_SET_ERGO(uintx, MaxHeapSize, smallest_heap_size); + _max_heap_byte_size = MaxHeapSize; } - NewSize = align_size_down(NewSize, _min_alignment); - MaxNewSize = align_size_down(MaxNewSize, _min_alignment); + // If needed, synchronize _min_heap_byte size and _initial_heap_byte_size + if (_min_heap_byte_size < smallest_heap_size) { + _min_heap_byte_size = smallest_heap_size; + if (InitialHeapSize < _min_heap_byte_size) { + FLAG_SET_ERGO(uintx, InitialHeapSize, smallest_heap_size); + _initial_heap_byte_size = smallest_heap_size; + } + } - // Check validity of heap flags - assert(NewSize % _min_alignment == 0, "eden space alignment"); - assert(MaxNewSize % _min_alignment == 0, "survivor space alignment"); + // Now take the actual NewSize into account. We will silently increase NewSize + // if the user specified a smaller value. + smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment)); + if (smallest_new_size != NewSize) { + FLAG_SET_ERGO(uintx, NewSize, smallest_new_size); + } + _initial_gen0_size = NewSize; + + if (!FLAG_IS_DEFAULT(MaxNewSize)) { + uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size); - if (NewSize < 3 * _min_alignment) { - // make sure there room for eden and two survivor spaces - vm_exit_during_initialization("Too small new size specified"); + if (MaxNewSize >= MaxHeapSize) { + // Make sure there is room for an old generation + uintx smaller_max_new_size = MaxHeapSize - _gen_alignment; + if (FLAG_IS_CMDLINE(MaxNewSize)) { + warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire " + "heap (" SIZE_FORMAT "k). A new max generation size of " SIZE_FORMAT "k will be used.", + MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K); + } + FLAG_SET_ERGO(uintx, MaxNewSize, smaller_max_new_size); + if (NewSize > MaxNewSize) { + FLAG_SET_ERGO(uintx, NewSize, MaxNewSize); + _initial_gen0_size = NewSize; + } + } else if (MaxNewSize < min_new_size) { + FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size); + } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) { + FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment)); + } + _max_gen0_size = MaxNewSize; } + + if (NewSize > MaxNewSize) { + // At this point this should only happen if the user specifies a large NewSize and/or + // a small (but not too small) MaxNewSize. + if (FLAG_IS_CMDLINE(MaxNewSize)) { + warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " + "A new max generation size of " SIZE_FORMAT "k will be used.", + NewSize/K, MaxNewSize/K, NewSize/K); + } + FLAG_SET_ERGO(uintx, MaxNewSize, NewSize); + _max_gen0_size = MaxNewSize; + } + if (SurvivorRatio < 1 || NewRatio < 1) { vm_exit_during_initialization("Invalid young gen ratio specified"); } + + DEBUG_ONLY(GenCollectorPolicy::assert_flags();) } void TwoGenerationCollectorPolicy::initialize_flags() { GenCollectorPolicy::initialize_flags(); - OldSize = align_size_down(OldSize, _min_alignment); + if (!is_size_aligned(OldSize, _gen_alignment)) { + FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment)); + } - if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) { + if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) { // NewRatio will be used later to set the young generation size so we use // it to calculate how big the heap should be based on the requested OldSize // and NewRatio. assert(NewRatio > 0, "NewRatio should have been set up earlier"); size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1); - calculated_heapsize = align_size_up(calculated_heapsize, _max_alignment); - MaxHeapSize = calculated_heapsize; - InitialHeapSize = calculated_heapsize; + calculated_heapsize = align_size_up(calculated_heapsize, _heap_alignment); + FLAG_SET_ERGO(uintx, MaxHeapSize, calculated_heapsize); + _max_heap_byte_size = MaxHeapSize; + FLAG_SET_ERGO(uintx, InitialHeapSize, calculated_heapsize); + _initial_heap_byte_size = InitialHeapSize; } - MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment); // adjust max heap size if necessary if (NewSize + OldSize > MaxHeapSize) { - if (FLAG_IS_CMDLINE(MaxHeapSize)) { + if (_max_heap_size_cmdline) { // somebody set a maximum heap size with the intention that we should not // exceed it. Adjust New/OldSize as necessary. uintx calculated_size = NewSize + OldSize; double shrink_factor = (double) MaxHeapSize / calculated_size; - // align - NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment); + uintx smaller_new_size = align_size_down((uintx)(NewSize * shrink_factor), _gen_alignment); + FLAG_SET_ERGO(uintx, NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size)); + _initial_gen0_size = NewSize; + // OldSize is already aligned because above we aligned MaxHeapSize to - // _max_alignment, and we just made sure that NewSize is aligned to - // _min_alignment. In initialize_flags() we verified that _max_alignment - // is a multiple of _min_alignment. - OldSize = MaxHeapSize - NewSize; + // _heap_alignment, and we just made sure that NewSize is aligned to + // _gen_alignment. In initialize_flags() we verified that _heap_alignment + // is a multiple of _gen_alignment. + FLAG_SET_ERGO(uintx, OldSize, MaxHeapSize - NewSize); } else { - MaxHeapSize = NewSize + OldSize; + FLAG_SET_ERGO(uintx, MaxHeapSize, align_size_up(NewSize + OldSize, _heap_alignment)); + _max_heap_byte_size = MaxHeapSize; } } - // need to do this again - MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment); - - // adjust max heap size if necessary - if (NewSize + OldSize > MaxHeapSize) { - if (FLAG_IS_CMDLINE(MaxHeapSize)) { - // somebody set a maximum heap size with the intention that we should not - // exceed it. Adjust New/OldSize as necessary. - uintx calculated_size = NewSize + OldSize; - double shrink_factor = (double) MaxHeapSize / calculated_size; - // align - NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment); - // OldSize is already aligned because above we aligned MaxHeapSize to - // _max_alignment, and we just made sure that NewSize is aligned to - // _min_alignment. In initialize_flags() we verified that _max_alignment - // is a multiple of _min_alignment. - OldSize = MaxHeapSize - NewSize; - } else { - MaxHeapSize = NewSize + OldSize; - } - } - // need to do this again - MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment); always_do_update_barrier = UseConcMarkSweepGC; - // Check validity of heap flags - assert(OldSize % _min_alignment == 0, "old space alignment"); - assert(MaxHeapSize % _max_alignment == 0, "maximum heap alignment"); + DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();) } // Values set on the command line win over any ergonomically @@ -281,7 +417,7 @@ void GenCollectorPolicy::initialize_size_info() { CollectorPolicy::initialize_size_info(); - // _min_alignment is used for alignment within a generation. + // _space_alignment is used for alignment within a generation. // There is additional alignment done down stream for some // collectors that sometimes causes unwanted rounding up of // generations sizes. @@ -289,35 +425,8 @@ // Determine maximum size of gen0 size_t max_new_size = 0; - if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) { - if (MaxNewSize < _min_alignment) { - max_new_size = _min_alignment; - } - if (MaxNewSize >= _max_heap_byte_size) { - max_new_size = align_size_down(_max_heap_byte_size - _min_alignment, - _min_alignment); - warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or " - "greater than the entire heap (" SIZE_FORMAT "k). A " - "new generation size of " SIZE_FORMAT "k will be used.", - MaxNewSize/K, _max_heap_byte_size/K, max_new_size/K); - } else { - max_new_size = align_size_down(MaxNewSize, _min_alignment); - } - - // The case for FLAG_IS_ERGO(MaxNewSize) could be treated - // specially at this point to just use an ergonomically set - // MaxNewSize to set max_new_size. For cases with small - // heaps such a policy often did not work because the MaxNewSize - // was larger than the entire heap. The interpretation given - // to ergonomically set flags is that the flags are set - // by different collectors for their own special needs but - // are not allowed to badly shape the heap. This allows the - // different collectors to decide what's best for themselves - // without having to factor in the overall heap shape. It - // can be the case in the future that the collectors would - // only make "wise" ergonomics choices and this policy could - // just accept those choices. The choices currently made are - // not always "wise". + if (!FLAG_IS_DEFAULT(MaxNewSize)) { + max_new_size = MaxNewSize; } else { max_new_size = scale_by_NewRatio_aligned(_max_heap_byte_size); // Bound the maximum size by NewSize below (since it historically @@ -386,11 +495,22 @@ _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size); } + // Write back to flags if necessary + if (NewSize != _initial_gen0_size) { + FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size); + } + + if (MaxNewSize != _max_gen0_size) { + FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size); + } + if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, _min_gen0_size, _initial_gen0_size, _max_gen0_size); } + + DEBUG_ONLY(GenCollectorPolicy::assert_size_info();) } // Call this method during the sizing of the gen1 to make @@ -403,23 +523,18 @@ // keeping it simple also seems a worthwhile goal. bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - const size_t heap_size, - const size_t min_gen1_size) { + const size_t heap_size) { bool result = false; - if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { - if ((heap_size < (*gen0_size_ptr + min_gen1_size)) && - (heap_size >= min_gen1_size + _min_alignment)) { - // Adjust gen0 down to accommodate min_gen1_size - *gen0_size_ptr = heap_size - min_gen1_size; - *gen0_size_ptr = - MAX2((uintx)align_size_down(*gen0_size_ptr, _min_alignment), _min_alignment); - assert(*gen0_size_ptr > 0, "Min gen0 is too large"); + if ((*gen0_size_ptr + *gen1_size_ptr) > heap_size) { + uintx smallest_new_size = young_gen_size_lower_bound(); + if ((heap_size < (*gen0_size_ptr + _min_gen1_size)) && + (heap_size >= _min_gen1_size + smallest_new_size)) { + // Adjust gen0 down to accommodate _min_gen1_size + *gen0_size_ptr = align_size_down_bounded(heap_size - _min_gen1_size, _gen_alignment); result = true; } else { - *gen1_size_ptr = heap_size - *gen0_size_ptr; - *gen1_size_ptr = - MAX2((uintx)align_size_down(*gen1_size_ptr, _min_alignment), _min_alignment); + *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment); } } return result; @@ -440,41 +555,36 @@ // The maximum gen1 size can be determined from the maximum gen0 // and maximum heap size since no explicit flags exits // for setting the gen1 maximum. - _max_gen1_size = _max_heap_byte_size - _max_gen0_size; - _max_gen1_size = - MAX2((uintx)align_size_down(_max_gen1_size, _min_alignment), _min_alignment); + _max_gen1_size = MAX2(_max_heap_byte_size - _max_gen0_size, _gen_alignment); + // If no explicit command line flag has been set for the // gen1 size, use what is left for gen1. - if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) { - // The user has not specified any value or ergonomics - // has chosen a value (which may or may not be consistent + if (!FLAG_IS_CMDLINE(OldSize)) { + // The user has not specified any value but the ergonomics + // may have chosen a value (which may or may not be consistent // with the overall heap size). In either case make // the minimum, maximum and initial sizes consistent // with the gen0 sizes and the overall heap sizes. - assert(_min_heap_byte_size > _min_gen0_size, - "gen0 has an unexpected minimum size"); - _min_gen1_size = _min_heap_byte_size - _min_gen0_size; - _min_gen1_size = - MAX2((uintx)align_size_down(_min_gen1_size, _min_alignment), _min_alignment); - _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size; - _initial_gen1_size = - MAX2((uintx)align_size_down(_initial_gen1_size, _min_alignment), _min_alignment); + _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment); + _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment); + // _max_gen1_size has already been made consistent above + FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size); } else { // It's been explicitly set on the command line. Use the // OldSize and then determine the consequences. - _min_gen1_size = OldSize; + _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size); _initial_gen1_size = OldSize; // If the user has explicitly set an OldSize that is inconsistent // with other command line flags, issue a warning. // The generation minimums and the overall heap mimimum should - // be within one heap alignment. - if ((_min_gen1_size + _min_gen0_size + _min_alignment) < _min_heap_byte_size) { + // be within one generation alignment. + if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) { warning("Inconsistency between minimum heap size and minimum " "generation sizes: using minimum heap = " SIZE_FORMAT, _min_heap_byte_size); } - if ((OldSize > _max_gen1_size)) { + if (OldSize > _max_gen1_size) { warning("Inconsistency between maximum heap size and maximum " "generation sizes: using maximum heap = " SIZE_FORMAT " -XX:OldSize flag is being ignored", @@ -482,8 +592,7 @@ } // If there is an inconsistency between the OldSize and the minimum and/or // initial size of gen0, since OldSize was explicitly set, OldSize wins. - if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, - _min_heap_byte_size, OldSize)) { + if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, _min_heap_byte_size)) { if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, @@ -492,7 +601,7 @@ } // Initial size if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, - _initial_heap_byte_size, OldSize)) { + _initial_heap_byte_size)) { if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, @@ -507,11 +616,26 @@ _initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size); _initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size); + // Write back to flags if necessary + if (NewSize != _initial_gen0_size) { + FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size); + } + + if (MaxNewSize != _max_gen0_size) { + FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size); + } + + if (OldSize != _initial_gen1_size) { + FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size); + } + if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 " SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT, _min_gen1_size, _initial_gen1_size, _max_gen1_size); } + + DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_size_info();) } HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size, @@ -605,9 +729,7 @@ gc_count_before = Universe::heap()->total_collections(); } - VM_GenCollectForAllocation op(size, - is_tlab, - gc_count_before); + VM_GenCollectForAllocation op(size, is_tlab, gc_count_before); VMThread::execute(&op); if (op.prologue_succeeded()) { result = op.result(); @@ -836,14 +958,16 @@ // MarkSweepPolicy methods // -MarkSweepPolicy::MarkSweepPolicy() { - initialize_all(); +void MarkSweepPolicy::initialize_alignments() { + _space_alignment = _gen_alignment = (uintx)Generation::GenGrain; + _heap_alignment = compute_heap_alignment(); } void MarkSweepPolicy::initialize_generations() { _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL); - if (_generations == NULL) + if (_generations == NULL) { vm_exit_during_initialization("Unable to allocate gen spec"); + } if (UseParNewGC) { _generations[0] = new GenerationSpec(Generation::ParNew, _initial_gen0_size, _max_gen0_size); @@ -852,8 +976,9 @@ } _generations[1] = new GenerationSpec(Generation::MarkSweepCompact, _initial_gen1_size, _max_gen1_size); - if (_generations[0] == NULL || _generations[1] == NULL) + if (_generations[0] == NULL || _generations[1] == NULL) { vm_exit_during_initialization("Unable to allocate gen spec"); + } } void MarkSweepPolicy::initialize_gc_policy_counters() { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/collectorPolicy.hpp --- a/src/share/vm/memory/collectorPolicy.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/collectorPolicy.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -61,17 +61,23 @@ protected: GCPolicyCounters* _gc_policy_counters; - // Requires that the concrete subclass sets the alignment constraints - // before calling. + virtual void initialize_alignments() = 0; virtual void initialize_flags(); virtual void initialize_size_info(); + DEBUG_ONLY(virtual void assert_flags();) + DEBUG_ONLY(virtual void assert_size_info();) + size_t _initial_heap_byte_size; size_t _max_heap_byte_size; size_t _min_heap_byte_size; - size_t _min_alignment; - size_t _max_alignment; + size_t _space_alignment; + size_t _heap_alignment; + + // Needed to keep information if MaxHeapSize was set on the command line + // when the flag value is aligned etc by ergonomics + bool _max_heap_size_cmdline; // The sizing of the heap are controlled by a sizing policy. AdaptiveSizePolicy* _size_policy; @@ -79,6 +85,7 @@ // Set to true when policy wants soft refs cleared. // Reset to false by gc after it clears all soft refs. bool _should_clear_all_soft_refs; + // Set to true by the GC if the just-completed gc cleared all // softrefs. This is set to true whenever a gc clears all softrefs, and // set to false each time gc returns to the mutator. For example, in the @@ -86,23 +93,20 @@ // mem_allocate() where it returns op.result() bool _all_soft_refs_clear; - CollectorPolicy() : - _min_alignment(1), - _max_alignment(1), - _initial_heap_byte_size(0), - _max_heap_byte_size(0), - _min_heap_byte_size(0), - _size_policy(NULL), - _should_clear_all_soft_refs(false), - _all_soft_refs_clear(false) - {} + CollectorPolicy(); public: - // Return maximum heap alignment that may be imposed by the policy - static size_t compute_max_alignment(); + virtual void initialize_all() { + initialize_alignments(); + initialize_flags(); + initialize_size_info(); + } - size_t min_alignment() { return _min_alignment; } - size_t max_alignment() { return _max_alignment; } + // Return maximum heap alignment that may be imposed by the policy + static size_t compute_heap_alignment(); + + size_t space_alignment() { return _space_alignment; } + size_t heap_alignment() { return _heap_alignment; } size_t initial_heap_byte_size() { return _initial_heap_byte_size; } size_t max_heap_byte_size() { return _max_heap_byte_size; } @@ -151,7 +155,6 @@ virtual BarrierSet::Name barrier_set_name() = 0; - virtual GenRemSet::Name rem_set_name() = 0; // Create the remembered set (to cover the given reserved region, // allowing breaking up into at most "max_covered_regions"). @@ -195,6 +198,9 @@ return false; } + // Do any updates required to global flags that are due to heap initialization + // changes + virtual void post_heap_initialize() = 0; }; class ClearedAllSoftRefs : public StackObj { @@ -219,6 +225,10 @@ size_t _initial_gen0_size; size_t _max_gen0_size; + // _gen_alignment and _space_alignment will have the same value most of the + // time. When using large pages they can differ. + size_t _gen_alignment; + GenerationSpec **_generations; // Return true if an allocation should be attempted in the older @@ -229,41 +239,50 @@ void initialize_flags(); void initialize_size_info(); + DEBUG_ONLY(void assert_flags();) + DEBUG_ONLY(void assert_size_info();) + // Try to allocate space by expanding the heap. virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); - // Scale the base_size by NewRation according to + // Compute max heap alignment + size_t compute_max_alignment(); + + // Scale the base_size by NewRatio according to // result = base_size / (NewRatio + 1) // and align by min_alignment() size_t scale_by_NewRatio_aligned(size_t base_size); - // Bound the value by the given maximum minus the - // min_alignment. + // Bound the value by the given maximum minus the min_alignment size_t bound_minus_alignment(size_t desired_size, size_t maximum_size); public: + GenCollectorPolicy(); + // Accessors size_t min_gen0_size() { return _min_gen0_size; } size_t initial_gen0_size() { return _initial_gen0_size; } size_t max_gen0_size() { return _max_gen0_size; } + size_t gen_alignment() { return _gen_alignment; } virtual int number_of_generations() = 0; - virtual GenerationSpec **generations() { + virtual GenerationSpec **generations() { assert(_generations != NULL, "Sanity check"); return _generations; } virtual GenCollectorPolicy* as_generation_policy() { return this; } - virtual void initialize_generations() = 0; + virtual void initialize_generations() { }; virtual void initialize_all() { - initialize_flags(); - initialize_size_info(); + CollectorPolicy::initialize_all(); initialize_generations(); } + size_t young_gen_size_lower_bound(); + HeapWord* mem_allocate_work(size_t size, bool is_tlab, bool* gc_overhead_limit_was_exceeded); @@ -274,6 +293,10 @@ virtual void initialize_size_policy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size); + + virtual void post_heap_initialize() { + assert(_max_gen0_size == MaxNewSize, "Should be taken care of by initialize_size_info"); + } }; // All of hotspot's current collectors are subtypes of this @@ -290,9 +313,14 @@ void initialize_flags(); void initialize_size_info(); - void initialize_generations() { ShouldNotReachHere(); } + + DEBUG_ONLY(void assert_flags();) + DEBUG_ONLY(void assert_size_info();) public: + TwoGenerationCollectorPolicy() : GenCollectorPolicy(), _min_gen1_size(0), + _initial_gen1_size(0), _max_gen1_size(0) {} + // Accessors size_t min_gen1_size() { return _min_gen1_size; } size_t initial_gen1_size() { return _initial_gen1_size; } @@ -301,25 +329,25 @@ // Inherited methods TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; } - int number_of_generations() { return 2; } - BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; } - GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; } + int number_of_generations() { return 2; } + BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; } virtual CollectorPolicy::Name kind() { return CollectorPolicy::TwoGenerationCollectorPolicyKind; } - // Returns true is gen0 sizes were adjusted + // Returns true if gen0 sizes were adjusted bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - const size_t heap_size, const size_t min_gen1_size); + const size_t heap_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { protected: + void initialize_alignments(); void initialize_generations(); public: - MarkSweepPolicy(); + MarkSweepPolicy() {} MarkSweepPolicy* as_mark_sweep_policy() { return this; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/defNewGeneration.cpp --- a/src/share/vm/memory/defNewGeneration.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/defNewGeneration.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -204,7 +204,7 @@ // Compute the maximum eden and survivor space sizes. These sizes // are computed assuming the entire reserved space is committed. // These values are exported as performance counters. - uintx alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment(); + uintx alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment(); uintx size = _virtual_space.reserved_size(); _max_survivor_size = compute_survivor_size(size, alignment); _max_eden_size = size - (2*_max_survivor_size); @@ -235,7 +235,7 @@ bool clear_space, bool mangle_space) { uintx alignment = - GenCollectedHeap::heap()->collector_policy()->min_alignment(); + GenCollectedHeap::heap()->collector_policy()->space_alignment(); // If the spaces are being cleared (only done at heap initialization // currently), the survivor spaces need not be empty. @@ -473,7 +473,7 @@ } size_t DefNewGeneration::max_capacity() const { - const size_t alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment(); + const size_t alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment(); const size_t reserved_bytes = reserved().byte_size(); return reserved_bytes - compute_survivor_size(reserved_bytes, alignment); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/genCollectedHeap.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -111,7 +111,7 @@ int n_covered_regions = 0; ReservedSpace heap_rs; - size_t heap_alignment = collector_policy()->max_alignment(); + size_t heap_alignment = collector_policy()->heap_alignment(); heap_address = allocate(heap_alignment, &total_reserved, &n_covered_regions, &heap_rs); @@ -1053,12 +1053,6 @@ } } -void GenCollectedHeap::compute_new_generation_sizes(int collectedGen) { - for (int i = 0; i <= collectedGen; i++) { - _gens[i]->compute_new_size(); - } -} - GenCollectedHeap* GenCollectedHeap::heap() { assert(_gch != NULL, "Uninitialized access to GenCollectedHeap::heap()"); assert(_gch->kind() == CollectedHeap::GenCollectedHeap, "not a generational heap"); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/genCollectedHeap.hpp --- a/src/share/vm/memory/genCollectedHeap.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/genCollectedHeap.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -86,10 +86,6 @@ NOT_PRODUCT(static size_t _skip_header_HeapWords;) protected: - // Directs each generation up to and including "collectedGen" to recompute - // its desired size. - void compute_new_generation_sizes(int collectedGen); - // Helper functions for allocation HeapWord* attempt_allocation(size_t size, bool is_tlab, diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/metaspace.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -56,7 +56,7 @@ MetaWord* last_allocated = 0; -size_t Metaspace::_class_metaspace_size; +size_t Metaspace::_compressed_class_space_size; // Used in declarations in SpaceManager and ChunkManager enum ChunkIndex { @@ -2843,6 +2843,8 @@ #define VIRTUALSPACEMULTIPLIER 2 #ifdef _LP64 +static const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1); + void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address cds_base) { // Figure out the narrow_klass_base and the narrow_klass_shift. The // narrow_klass_base is the lower of the metaspace base and the cds base @@ -2852,14 +2854,22 @@ address higher_address; if (UseSharedSpaces) { higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), - (address)(metaspace_base + class_metaspace_size())); + (address)(metaspace_base + compressed_class_space_size())); lower_base = MIN2(metaspace_base, cds_base); } else { - higher_address = metaspace_base + class_metaspace_size(); + higher_address = metaspace_base + compressed_class_space_size(); lower_base = metaspace_base; + + uint64_t klass_encoding_max = UnscaledClassSpaceMax << LogKlassAlignmentInBytes; + // If compressed class space fits in lower 32G, we don't need a base. + if (higher_address <= (address)klass_encoding_max) { + lower_base = 0; // effectively lower base is zero. + } } + Universe::set_narrow_klass_base(lower_base); - if ((uint64_t)(higher_address - lower_base) < (uint64_t)max_juint) { + + if ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) { Universe::set_narrow_klass_shift(0); } else { assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces"); @@ -2874,24 +2884,24 @@ assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs"); address lower_base = MIN2((address)metaspace_base, cds_base); address higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), - (address)(metaspace_base + class_metaspace_size())); - return ((uint64_t)(higher_address - lower_base) < (uint64_t)max_juint); + (address)(metaspace_base + compressed_class_space_size())); + return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax); } // Try to allocate the metaspace at the requested addr. void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) { assert(using_class_space(), "called improperly"); assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs"); - assert(class_metaspace_size() < KlassEncodingMetaspaceMax, + assert(compressed_class_space_size() < KlassEncodingMetaspaceMax, "Metaspace size is too big"); - assert_is_ptr_aligned(requested_addr, _reserve_alignment); - assert_is_ptr_aligned(cds_base, _reserve_alignment); - assert_is_size_aligned(class_metaspace_size(), _reserve_alignment); + assert_is_ptr_aligned(requested_addr, _reserve_alignment); + assert_is_ptr_aligned(cds_base, _reserve_alignment); + assert_is_size_aligned(compressed_class_space_size(), _reserve_alignment); // Don't use large pages for the class space. bool large_pages = false; - ReservedSpace metaspace_rs = ReservedSpace(class_metaspace_size(), + ReservedSpace metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment, large_pages, requested_addr, 0); @@ -2906,7 +2916,7 @@ while (!metaspace_rs.is_reserved() && (addr + increment > addr) && can_use_cds_with_metaspace_addr(addr + increment, cds_base)) { addr = addr + increment; - metaspace_rs = ReservedSpace(class_metaspace_size(), + metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment, large_pages, addr, 0); } } @@ -2917,11 +2927,11 @@ // initialization has happened that depends on UseCompressedClassPointers. // So, UseCompressedClassPointers cannot be turned off at this point. if (!metaspace_rs.is_reserved()) { - metaspace_rs = ReservedSpace(class_metaspace_size(), + metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment, large_pages); if (!metaspace_rs.is_reserved()) { vm_exit_during_initialization(err_msg("Could not allocate metaspace: %d bytes", - class_metaspace_size())); + compressed_class_space_size())); } } } @@ -2943,8 +2953,8 @@ if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { gclog_or_tty->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: " SIZE_FORMAT, Universe::narrow_klass_base(), Universe::narrow_klass_shift()); - gclog_or_tty->print_cr("Metaspace Size: " SIZE_FORMAT " Address: " PTR_FORMAT " Req Addr: " PTR_FORMAT, - class_metaspace_size(), metaspace_rs.base(), requested_addr); + gclog_or_tty->print_cr("Compressed class space size: " SIZE_FORMAT " Address: " PTR_FORMAT " Req Addr: " PTR_FORMAT, + compressed_class_space_size(), metaspace_rs.base(), requested_addr); } } @@ -2965,11 +2975,6 @@ #endif -// Align down. If the aligning result in 0, return 'alignment'. -static size_t restricted_align_down(size_t size, size_t alignment) { - return MAX2(alignment, align_size_down_(size, alignment)); -} - void Metaspace::ergo_initialize() { if (DumpSharedSpaces) { // Using large pages when dumping the shared archive is currently not implemented. @@ -2992,13 +2997,13 @@ // Ideally, we would be able to set the default value of MaxMetaspaceSize in // globals.hpp to the aligned value, but this is not possible, since the // alignment depends on other flags being parsed. - MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, _reserve_alignment); + MaxMetaspaceSize = align_size_down_bounded(MaxMetaspaceSize, _reserve_alignment); if (MetaspaceSize > MaxMetaspaceSize) { MetaspaceSize = MaxMetaspaceSize; } - MetaspaceSize = restricted_align_down(MetaspaceSize, _commit_alignment); + MetaspaceSize = align_size_down_bounded(MetaspaceSize, _commit_alignment); assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize"); @@ -3006,11 +3011,11 @@ vm_exit_during_initialization("Too small initial Metaspace size"); } - MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, _commit_alignment); - MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, _commit_alignment); - - CompressedClassSpaceSize = restricted_align_down(CompressedClassSpaceSize, _reserve_alignment); - set_class_metaspace_size(CompressedClassSpaceSize); + MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment); + MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment); + + CompressedClassSpaceSize = align_size_down_bounded(CompressedClassSpaceSize, _reserve_alignment); + set_compressed_class_space_size(CompressedClassSpaceSize); } void Metaspace::global_initialize() { @@ -3039,12 +3044,12 @@ } #ifdef _LP64 - if (cds_total + class_metaspace_size() > (uint64_t)max_juint) { + if (cds_total + compressed_class_space_size() > UnscaledClassSpaceMax) { vm_exit_during_initialization("Unable to dump shared archive.", err_msg("Size of archive (" SIZE_FORMAT ") + compressed class space (" SIZE_FORMAT ") == total (" SIZE_FORMAT ") is larger than compressed " - "klass limit: " SIZE_FORMAT, cds_total, class_metaspace_size(), - cds_total + class_metaspace_size(), (size_t)max_juint)); + "klass limit: " SIZE_FORMAT, cds_total, compressed_class_space_size(), + cds_total + compressed_class_space_size(), UnscaledClassSpaceMax)); } // Set the compressed klass pointer base so that decoding of these pointers works @@ -3092,7 +3097,8 @@ cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment); allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address); } else { - allocate_metaspace_compressed_klass_ptrs((char *)CompressedKlassPointersBase, 0); + char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment); + allocate_metaspace_compressed_klass_ptrs(base, 0); } } #endif @@ -3354,6 +3360,11 @@ return result; } +size_t Metaspace::class_chunk_size(size_t word_size) { + assert(using_class_space(), "Has to use class space"); + return class_vsm()->calc_chunk_size(word_size); +} + void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) { // If result is still null, we are out of memory. if (Verbose && TraceMetadataChunkAllocation) { @@ -3365,9 +3376,19 @@ MetaspaceAux::dump(gclog_or_tty); } + bool out_of_compressed_class_space = false; + if (is_class_space_allocation(mdtype)) { + Metaspace* metaspace = loader_data->metaspace_non_null(); + out_of_compressed_class_space = + MetaspaceAux::committed_bytes(Metaspace::ClassType) + + (metaspace->class_chunk_size(word_size) * BytesPerWord) > + CompressedClassSpaceSize; + } + // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - const char* space_string = is_class_space_allocation(mdtype) ? "Compressed class space" : - "Metadata space"; + const char* space_string = out_of_compressed_class_space ? + "Compressed class space" : "Metaspace"; + report_java_out_of_memory(space_string); if (JvmtiExport::should_post_resource_exhausted()) { @@ -3380,7 +3401,7 @@ vm_exit_during_initialization("OutOfMemoryError", space_string); } - if (is_class_space_allocation(mdtype)) { + if (out_of_compressed_class_space) { THROW_OOP(Universe::out_of_memory_error_class_metaspace()); } else { THROW_OOP(Universe::out_of_memory_error_metaspace()); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/metaspace.hpp --- a/src/share/vm/memory/metaspace.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/metaspace.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -115,13 +115,13 @@ static size_t align_word_size_up(size_t); // Aligned size of the metaspace. - static size_t _class_metaspace_size; + static size_t _compressed_class_space_size; - static size_t class_metaspace_size() { - return _class_metaspace_size; + static size_t compressed_class_space_size() { + return _compressed_class_space_size; } - static void set_class_metaspace_size(size_t metaspace_size) { - _class_metaspace_size = metaspace_size; + static void set_compressed_class_space_size(size_t size) { + _compressed_class_space_size = size; } static size_t _first_chunk_word_size; @@ -192,6 +192,8 @@ AllocRecord * _alloc_record_head; AllocRecord * _alloc_record_tail; + size_t class_chunk_size(size_t word_size); + public: Metaspace(Mutex* lock, MetaspaceType type); @@ -252,6 +254,7 @@ static bool is_class_space_allocation(MetadataType mdType) { return mdType == ClassType && using_class_space(); } + }; class MetaspaceAux : AllStatic { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/sharedHeap.cpp --- a/src/share/vm/memory/sharedHeap.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/sharedHeap.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -247,6 +247,7 @@ } void SharedHeap::post_initialize() { + CollectedHeap::post_initialize(); ref_processing_init(); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/memory/universe.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -677,13 +677,13 @@ // HeapBased - Use compressed oops with heap base + encoding. // 4Gb -static const uint64_t NarrowOopHeapMax = (uint64_t(max_juint) + 1); +static const uint64_t UnscaledOopHeapMax = (uint64_t(max_juint) + 1); // 32Gb -// OopEncodingHeapMax == NarrowOopHeapMax << LogMinObjAlignmentInBytes; +// OopEncodingHeapMax == UnscaledOopHeapMax << LogMinObjAlignmentInBytes; char* Universe::preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode) { assert(is_size_aligned((size_t)OopEncodingHeapMax, alignment), "Must be"); - assert(is_size_aligned((size_t)NarrowOopHeapMax, alignment), "Must be"); + assert(is_size_aligned((size_t)UnscaledOopHeapMax, alignment), "Must be"); assert(is_size_aligned(heap_size, alignment), "Must be"); uintx heap_base_min_address_aligned = align_size_up(HeapBaseMinAddress, alignment); @@ -702,20 +702,40 @@ // If the total size is small enough to allow UnscaledNarrowOop then // just use UnscaledNarrowOop. } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop)) { - if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) && + if ((total_size <= UnscaledOopHeapMax) && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary - base = (NarrowOopHeapMax - heap_size); + base = (UnscaledOopHeapMax - heap_size); } else { // Can't reserve with NarrowOopShift == 0 Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); + if (mode == UnscaledNarrowOop || - mode == ZeroBasedNarrowOop && total_size <= NarrowOopHeapMax) { + mode == ZeroBasedNarrowOop && total_size <= UnscaledOopHeapMax) { + // Use zero based compressed oops with encoding and // place heap's top on the 32Gb boundary in case // total_size > 4Gb or failed to reserve below 4Gb. - base = (OopEncodingHeapMax - heap_size); + uint64_t heap_top = OopEncodingHeapMax; + + // For small heaps, save some space for compressed class pointer + // space so it can be decoded with no base. + if (UseCompressedClassPointers && !UseSharedSpaces && + OopEncodingHeapMax <= 32*G) { + + uint64_t class_space = align_size_up(CompressedClassSpaceSize, alignment); + assert(is_size_aligned((size_t)OopEncodingHeapMax-class_space, + alignment), "difference must be aligned too"); + uint64_t new_top = OopEncodingHeapMax-class_space; + + if (total_size <= new_top) { + heap_top = new_top; + } + } + + // Align base to the adjusted top of the heap + base = heap_top - heap_size; } } } else { @@ -737,7 +757,7 @@ // Set to a non-NULL value so the ReservedSpace ctor computes // the correct no-access prefix. // The final value will be set in initialize_heap() below. - Universe::set_narrow_oop_base((address)NarrowOopHeapMax); + Universe::set_narrow_oop_base((address)UnscaledOopHeapMax); #ifdef _WIN64 if (UseLargePages) { // Cannot allocate guard pages for implicit checks in indexed @@ -765,6 +785,7 @@ } else if (UseG1GC) { #if INCLUDE_ALL_GCS G1CollectorPolicy* g1p = new G1CollectorPolicy(); + g1p->initialize_all(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; #else // INCLUDE_ALL_GCS @@ -789,6 +810,7 @@ } else { // default old generation gc_policy = new MarkSweepPolicy(); } + gc_policy->initialize_all(); Universe::_collectedHeap = new GenCollectedHeap(gc_policy); } @@ -833,7 +855,7 @@ Universe::set_narrow_oop_use_implicit_null_checks(true); } #endif // _WIN64 - if((uint64_t)Universe::heap()->reserved_region().end() > NarrowOopHeapMax) { + if((uint64_t)Universe::heap()->reserved_region().end() > UnscaledOopHeapMax) { // Can't reserve heap below 4Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } else { @@ -1021,7 +1043,7 @@ Universe::_virtual_machine_error_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); - Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false); + Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false); if (!DumpSharedSpaces) { // These are the only Java fields that are currently set during shared space dumping. @@ -1029,7 +1051,7 @@ Handle msg = java_lang_String::create_from_str("Java heap space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg()); - msg = java_lang_String::create_from_str("Metadata space", CHECK_false); + msg = java_lang_String::create_from_str("Metaspace", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg()); msg = java_lang_String::create_from_str("Compressed class space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg()); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/cpCache.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -554,24 +554,37 @@ // Implementation of ConstantPoolCache ConstantPoolCache* ConstantPoolCache::allocate(ClassLoaderData* loader_data, - int length, const intStack& index_map, + const intStack& invokedynamic_index_map, const intStack& invokedynamic_map, TRAPS) { + + const int length = index_map.length() + invokedynamic_index_map.length(); int size = ConstantPoolCache::size(length); return new (loader_data, size, false, MetaspaceObj::ConstantPoolCacheType, THREAD) - ConstantPoolCache(length, index_map, invokedynamic_map); + ConstantPoolCache(length, index_map, invokedynamic_index_map, invokedynamic_map); } void ConstantPoolCache::initialize(const intArray& inverse_index_map, + const intArray& invokedynamic_inverse_index_map, const intArray& invokedynamic_references_map) { - assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache"); - for (int i = 0; i < length(); i++) { + for (int i = 0; i < inverse_index_map.length(); i++) { ConstantPoolCacheEntry* e = entry_at(i); int original_index = inverse_index_map[i]; e->initialize_entry(original_index); assert(entry_at(i) == e, "sanity"); } + + // Append invokedynamic entries at the end + int invokedynamic_offset = inverse_index_map.length(); + for (int i = 0; i < invokedynamic_inverse_index_map.length(); i++) { + int offset = i + invokedynamic_offset; + ConstantPoolCacheEntry* e = entry_at(offset); + int original_index = invokedynamic_inverse_index_map[i]; + e->initialize_entry(original_index); + assert(entry_at(offset) == e, "sanity"); + } + for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) { const int cpci = invokedynamic_references_map[ref]; if (cpci >= 0) { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/cpCache.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -31,6 +31,10 @@ class PSPromotionManager; +// The ConstantPoolCache is not a cache! It is the resolution table that the +// interpreter uses to avoid going into the runtime and a way to access resolved +// values. + // A ConstantPoolCacheEntry describes an individual entry of the constant // pool cache. There's 2 principal kinds of entries: field entries for in- // stance & static field access, and method entries for invokes. Some of @@ -392,26 +396,33 @@ friend class MetadataFactory; private: int _length; - ConstantPool* _constant_pool; // the corresponding constant pool + ConstantPool* _constant_pool; // the corresponding constant pool // Sizing debug_only(friend class ClassVerifier;) // Constructor - ConstantPoolCache(int length, const intStack& inverse_index_map, + ConstantPoolCache(int length, + const intStack& inverse_index_map, + const intStack& invokedynamic_inverse_index_map, const intStack& invokedynamic_references_map) : - _length(length), _constant_pool(NULL) { - initialize(inverse_index_map, invokedynamic_references_map); + _length(length), + _constant_pool(NULL) { + initialize(inverse_index_map, invokedynamic_inverse_index_map, + invokedynamic_references_map); for (int i = 0; i < length; i++) { assert(entry_at(i)->is_f1_null(), "Failed to clear?"); } } // Initialization - void initialize(const intArray& inverse_index_map, const intArray& invokedynamic_references_map); + void initialize(const intArray& inverse_index_map, + const intArray& invokedynamic_inverse_index_map, + const intArray& invokedynamic_references_map); public: - static ConstantPoolCache* allocate(ClassLoaderData* loader_data, int length, - const intStack& inverse_index_map, + static ConstantPoolCache* allocate(ClassLoaderData* loader_data, + const intStack& cp_cache_map, + const intStack& invokedynamic_cp_cache_map, const intStack& invokedynamic_references_map, TRAPS); bool is_constantPoolCache() const { return true; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2211,6 +2211,10 @@ 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); + } } } } @@ -2393,15 +2397,38 @@ const char* InstanceKlass::signature_name() const { + int hash_len = 0; + char hash_buf[40]; + + // If this is an anonymous class, append a hash to make the name unique + if (is_anonymous()) { + assert(EnableInvokeDynamic, "EnableInvokeDynamic was not set."); + intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0; + sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash); + hash_len = (int)strlen(hash_buf); + } + + // Get the internal name as a c string const char* src = (const char*) (name()->as_C_string()); const int src_length = (int)strlen(src); - char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3); - int src_index = 0; + + char* dest = NEW_RESOURCE_ARRAY(char, src_length + hash_len + 3); + + // Add L as type indicator int dest_index = 0; dest[dest_index++] = 'L'; - while (src_index < src_length) { + + // Add the actual class name + for (int src_index = 0; src_index < src_length; ) { dest[dest_index++] = src[src_index++]; } + + // If we have a hash, append it + for (int hash_index = 0; hash_index < hash_len; ) { + dest[dest_index++] = hash_buf[hash_index++]; + } + + // Add the semicolon and the NULL dest[dest_index++] = ';'; dest[dest_index] = '\0'; return dest; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/klassVtable.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -86,7 +86,11 @@ get_mirandas(&new_mirandas, all_mirandas, super, methods, NULL, local_interfaces); *num_new_mirandas = new_mirandas.length(); - vtable_length += *num_new_mirandas * vtableEntry::size(); + // Interfaces do not need interface methods in their vtables + // This includes miranda methods and during later processing, default methods + if (!class_flags.is_interface()) { + vtable_length += *num_new_mirandas * vtableEntry::size(); + } if (Universe::is_bootstrapping() && vtable_length == 0) { // array classes don't have their superclass set correctly during @@ -224,7 +228,11 @@ } // add miranda methods; it will also return the updated initialized - initialized = fill_in_mirandas(initialized); + // Interfaces do not need interface methods in their vtables + // This includes miranda methods and during later processing, default methods + if (!ik()->is_interface()) { + initialized = fill_in_mirandas(initialized); + } // In class hierarchies where the accessibility is not increasing (i.e., going from private -> // package_private -> public/protected), the vtable might actually be smaller than our initial @@ -264,12 +272,12 @@ _klass->internal_name(), sig, vtable_index); super_method->access_flags().print_on(tty); if (super_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } tty->print("overriders flags: "); target_method->access_flags().print_on(tty); if (target_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } } #endif /*PRODUCT*/ @@ -332,9 +340,15 @@ // An interface never allocates new vtable slots, only inherits old ones. // This method will either be assigned its own itable index later, // or be assigned an inherited vtable index in the loop below. - // default methods store their vtable indices in the inheritors default_vtable_indices - assert (default_index == -1, "interfaces don't store resolved default methods"); - target_method()->set_vtable_index(Method::pending_itable_index); + // default methods inherited by classes store their vtable indices + // in the inheritor's default_vtable_indices + // default methods inherited by interfaces may already have a + // valid itable index, if so, don't change it + // overpass methods in an interface will be assigned an itable index later + // by an inheriting class + if (!is_default || !target_method()->has_itable_index()) { + target_method()->set_vtable_index(Method::pending_itable_index); + } } // we need a new entry if there is no superclass @@ -441,7 +455,7 @@ target_klass->internal_name(), sig, i); super_method->access_flags().print_on(tty); if (super_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (super_method->is_overpass()) { tty->print("overpass"); @@ -449,7 +463,7 @@ tty->print("overriders flags: "); target_method->access_flags().print_on(tty); if (target_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (target_method->is_overpass()) { tty->print("overpass"); @@ -468,7 +482,7 @@ target_klass->internal_name(), sig,i); super_method->access_flags().print_on(tty); if (super_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (super_method->is_overpass()) { tty->print("overpass"); @@ -476,7 +490,7 @@ tty->print("overriders flags: "); target_method->access_flags().print_on(tty); if (target_method->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (target_method->is_overpass()) { tty->print("overpass"); @@ -494,8 +508,18 @@ #ifndef PRODUCT if (PrintVtables && Verbose) { ResourceMark rm; - tty->print_cr("adding %s::%s at index %d", _klass->internal_name(), - (m != NULL) ? m->name()->as_C_string() : "", index); + const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : ""; + tty->print("adding %s at index %d, flags: ", sig, index); + if (m != NULL) { + m->access_flags().print_on(tty); + if (m->is_default_method()) { + tty->print("default "); + } + if (m->is_overpass()) { + tty->print("overpass"); + } + } + tty->cr(); } #endif table()[index].set(m); @@ -631,8 +655,10 @@ if (mhk->is_interface()) { assert(m->is_public(), "should be public"); assert(ik()->implements_interface(method_holder) , "this class should implement the interface"); - assert(is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super()), "should be a miranda_method"); - return true; + // the search could find a miranda or a default method + if (is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super())) { + return true; + } } return false; } @@ -644,9 +670,10 @@ // the caller must make sure that the method belongs to an interface implemented by the class // Miranda methods only include public interface instance methods // Not private methods, not static methods, not default == concrete abstract +// Miranda methods also do not include overpass methods in interfaces bool klassVtable::is_miranda(Method* m, Array* class_methods, Array* default_methods, Klass* super) { - if (m->is_static() || m->is_private()) { + if (m->is_static() || m->is_private() || m->is_overpass()) { return false; } Symbol* name = m->name(); @@ -744,6 +771,8 @@ // Discover miranda methods ("miranda" = "interface abstract, no binding"), // and append them into the vtable starting at index initialized, // return the new value of initialized. +// Miranda methods use vtable entries, but do not get assigned a vtable_index +// The vtable_index is discovered by searching from the end of the vtable int klassVtable::fill_in_mirandas(int initialized) { GrowableArray mirandas(20); get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(), @@ -758,7 +787,7 @@ sig, initialized); meth->access_flags().print_on(tty); if (meth->is_default_method()) { - tty->print("default"); + tty->print("default "); } tty->cr(); } @@ -858,7 +887,7 @@ tty->print(" (%5d) ", i); m->access_flags().print_on(tty); if (m->is_default_method()) { - tty->print("default"); + tty->print("default "); } if (m->is_overpass()) { tty->print("overpass"); @@ -977,6 +1006,25 @@ if (interface_method_needs_itable_index(m)) { assert(!m->is_final_method(), "no final interface methods"); // If m is already assigned a vtable index, do not disturb it. + if (TraceItables && Verbose) { + ResourceMark rm; + const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : ""; + if (m->has_vtable_index()) { + tty->print("itable index %d for method: %s, flags: ", m->vtable_index(), sig); + } else { + tty->print("itable index %d for method: %s, flags: ", ime_num, sig); + } + if (m != NULL) { + m->access_flags().print_on(tty); + if (m->is_default_method()) { + tty->print("default "); + } + if (m->is_overpass()) { + tty->print("overpass"); + } + } + tty->cr(); + } if (!m->has_vtable_index()) { assert(m->vtable_index() == Method::pending_itable_index, "set by initialize_vtable"); m->set_itable_index(ime_num); @@ -1079,7 +1127,7 @@ tty->print("target_method flags: "); target()->access_flags().print_on(tty); if (target()->is_default_method()) { - tty->print("default"); + tty->print("default "); } tty->cr(); } @@ -1158,7 +1206,7 @@ tty->print(" (%5d) ", i); m->access_flags().print_on(tty); if (m->is_default_method()) { - tty->print("default"); + tty->print("default "); } tty->print(" -- "); m->print_name(tty); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/method.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1515,7 +1515,10 @@ return bp->orig_bytecode(); } } - ShouldNotReachHere(); + { + ResourceMark rm; + fatal(err_msg("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci)); + } return Bytecodes::_shouldnotreachhere; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/methodData.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -275,23 +275,23 @@ } bool TypeEntries::is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p) { - return !is_type_none(p) && - !((Klass*)klass_part(p))->is_loader_alive(is_alive_cl); + Klass* k = (Klass*)klass_part(p); + return k != NULL && k->is_loader_alive(is_alive_cl); } void TypeStackSlotEntries::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { for (int i = 0; i < _number_of_entries; i++) { intptr_t p = type(i); - if (is_loader_alive(is_alive_cl, p)) { - set_type(i, type_none()); + if (!is_loader_alive(is_alive_cl, p)) { + set_type(i, with_status((Klass*)NULL, p)); } } } void ReturnTypeEntry::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { intptr_t p = type(); - if (is_loader_alive(is_alive_cl, p)) { - set_type(type_none()); + if (!is_loader_alive(is_alive_cl, p)) { + set_type(with_status((Klass*)NULL, p)); } } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/oops/methodData.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -690,7 +690,6 @@ // recorded type: cell without bit 0 and 1 static intptr_t klass_part(intptr_t v) { intptr_t r = v & type_klass_mask; - assert (r != 0, "invalid"); return r; } @@ -698,7 +697,9 @@ static Klass* valid_klass(intptr_t k) { if (!is_type_none(k) && !is_type_unknown(k)) { - return (Klass*)klass_part(k); + Klass* res = (Klass*)klass_part(k); + assert(res != NULL, "invalid"); + return res; } else { return NULL; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/bytecodeInfo.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -389,6 +389,10 @@ return false; } if (inline_level() > _max_inline_level) { + if (callee_method->force_inline() && inline_level() > MaxForceInlineLevel) { + set_msg("MaxForceInlineLevel"); + return false; + } if (!callee_method->force_inline() || !IncrementalInline) { set_msg("inlining too deep"); return false; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/callGenerator.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -776,7 +776,7 @@ guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove const int vtable_index = Method::invalid_vtable_index; CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true); - assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); + assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; } @@ -846,7 +846,7 @@ } CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); - assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); + assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/compile.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -848,6 +848,7 @@ } #endif + NOT_PRODUCT( verify_barriers(); ) // Now that we know the size of all the monitors we can add a fixed slot // for the original deopt pc. @@ -3018,12 +3019,17 @@ // 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 - if (!out->is_Phi()) { - if (out->in(0) == NULL) { - out->set_req(0, non_throwing); - } else if (out->in(0) == ctrl) { - out->set_req(0, non_throwing); - } + // + // 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); } } } @@ -3368,6 +3374,72 @@ } } } + +// Verify GC barriers consistency +// Currently supported: +// - G1 pre-barriers (see GraphKit::g1_write_barrier_pre()) +void Compile::verify_barriers() { + if (UseG1GC) { + // Verify G1 pre-barriers + const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()); + + ResourceArea *area = Thread::current()->resource_area(); + Unique_Node_List visited(area); + Node_List worklist(area); + // We're going to walk control flow backwards starting from the Root + worklist.push(_root); + while (worklist.size() > 0) { + Node* x = worklist.pop(); + if (x == NULL || x == top()) continue; + if (visited.member(x)) { + continue; + } else { + visited.push(x); + } + + if (x->is_Region()) { + for (uint i = 1; i < x->req(); i++) { + worklist.push(x->in(i)); + } + } else { + worklist.push(x->in(0)); + // We are looking for the pattern: + // /->ThreadLocal + // If->Bool->CmpI->LoadB->AddP->ConL(marking_offset) + // \->ConI(0) + // We want to verify that the If and the LoadB have the same control + // See GraphKit::g1_write_barrier_pre() + if (x->is_If()) { + IfNode *iff = x->as_If(); + if (iff->in(1)->is_Bool() && iff->in(1)->in(1)->is_Cmp()) { + CmpNode *cmp = iff->in(1)->in(1)->as_Cmp(); + if (cmp->Opcode() == Op_CmpI && cmp->in(2)->is_Con() && cmp->in(2)->bottom_type()->is_int()->get_con() == 0 + && cmp->in(1)->is_Load()) { + LoadNode* load = cmp->in(1)->as_Load(); + if (load->Opcode() == Op_LoadB && load->in(2)->is_AddP() && load->in(2)->in(2)->Opcode() == Op_ThreadLocal + && load->in(2)->in(3)->is_Con() + && load->in(2)->in(3)->bottom_type()->is_intptr_t()->get_con() == marking_offset) { + + Node* if_ctrl = iff->in(0); + Node* load_ctrl = load->in(0); + + if (if_ctrl != load_ctrl) { + // Skip possible CProj->NeverBranch in infinite loops + if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) + && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { + if_ctrl = if_ctrl->in(0)->in(0); + } + } + assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match"); + } + } + } + } + } + } + } +} + #endif // The Compile object keeps track of failure reasons separately from the ciEnv. diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/compile.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -1148,6 +1148,9 @@ // graph is strongly connected from root in both directions. void verify_graph_edges(bool no_dead_code = false) PRODUCT_RETURN; + // Verify GC barrier patterns + void verify_barriers() PRODUCT_RETURN; + // End-of-run dumps. static void print_statistics() PRODUCT_RETURN; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/library_call.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2006,9 +2006,9 @@ Node* arg2 = NULL; if (is_increment) { - arg2 = intcon(1); + arg2 = intcon(1); } else { - arg2 = argument(1); + arg2 = argument(1); } Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) ); @@ -2056,7 +2056,7 @@ if (is_decrement) { arg2 = longcon(1); } else { - Node* arg2 = argument(2); // type long + arg2 = argument(2); // type long // argument(3) == TOP } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/loopTransform.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -713,6 +713,10 @@ 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: @@ -1960,7 +1964,7 @@ // Find loads off the surviving projection; remove their control edge for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { Node* cd = dp->fast_out(i); // Control-dependent node - if( cd->is_Load() ) { // Loads can now float around in the loop + if (cd->is_Load() && cd->depends_only_on_test()) { // Loads can now float around in the loop // Allow the load to float around in the loop, or before it // but NOT before the pre-loop. _igvn.replace_input_of(cd, 0, ctrl); // ctrl, not NULL diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/loopopts.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -42,6 +42,13 @@ // so disable this for now 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(), ""); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/matcher.cpp --- a/src/share/vm/opto/matcher.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/matcher.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -464,17 +464,17 @@ C->FIRST_STACK_mask().Clear(); // Add in the incoming argument area - OptoReg::Name init = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); - for (i = init; i < _in_arg_limit; i = OptoReg::add(i,1)) + OptoReg::Name init_in = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); + for (i = init_in; i < _in_arg_limit; i = OptoReg::add(i,1)) { C->FIRST_STACK_mask().Insert(i); - + } // Add in all bits past the outgoing argument area guarantee(RegMask::can_represent_arg(OptoReg::add(_out_arg_limit,-1)), "must be able to represent all call arguments in reg mask"); - init = _out_arg_limit; - for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) + OptoReg::Name init = _out_arg_limit; + for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) { C->FIRST_STACK_mask().Insert(i); - + } // Finally, set the "infinite stack" bit. C->FIRST_STACK_mask().set_AllStack(); @@ -506,16 +506,36 @@ idealreg2spillmask[Op_VecS]->OR(C->FIRST_STACK_mask()); } if (Matcher::vector_size_supported(T_FLOAT,2)) { + // For VecD we need dual alignment and 8 bytes (2 slots) for spills. + // RA guarantees such alignment since it is needed for Double and Long values. *idealreg2spillmask[Op_VecD] = *idealreg2regmask[Op_VecD]; idealreg2spillmask[Op_VecD]->OR(aligned_stack_mask); } if (Matcher::vector_size_supported(T_FLOAT,4)) { + // For VecX we need quadro alignment and 16 bytes (4 slots) for spills. + // + // RA can use input arguments stack slots for spills but until RA + // we don't know frame size and offset of input arg stack slots. + // + // Exclude last input arg stack slots to avoid spilling vectors there + // otherwise vector spills could stomp over stack slots in caller frame. + OptoReg::Name in = OptoReg::add(_in_arg_limit, -1); + for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecX); k++) { + aligned_stack_mask.Remove(in); + in = OptoReg::add(in, -1); + } aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecX); assert(aligned_stack_mask.is_AllStack(), "should be infinite stack"); *idealreg2spillmask[Op_VecX] = *idealreg2regmask[Op_VecX]; idealreg2spillmask[Op_VecX]->OR(aligned_stack_mask); } if (Matcher::vector_size_supported(T_FLOAT,8)) { + // For VecY we need octo alignment and 32 bytes (8 slots) for spills. + OptoReg::Name in = OptoReg::add(_in_arg_limit, -1); + for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecY); k++) { + aligned_stack_mask.Remove(in); + in = OptoReg::add(in, -1); + } aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecY); assert(aligned_stack_mask.is_AllStack(), "should be infinite stack"); *idealreg2spillmask[Op_VecY] = *idealreg2regmask[Op_VecY]; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/mathexactnode.hpp --- a/src/share/vm/opto/mathexactnode.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/mathexactnode.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -49,7 +49,7 @@ 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 Node::hash(); } + virtual uint hash() const { return NO_HASH; } virtual bool is_CFG() const { return false; } virtual uint ideal_reg() const { return NotAMachineReg; } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/memnode.hpp --- a/src/share/vm/opto/memnode.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/memnode.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -204,6 +204,17 @@ protected: const Type* load_array_final_field(const TypeKlassPtr *tkls, ciKlass* klass) const; + // depends_only_on_test is almost always true, and needs to be almost always + // true to enable key hoisting & commoning optimizations. However, for the + // special case of RawPtr loads from TLS top & end, and other loads performed by + // GC barriers, the control edge carries the dependence preventing hoisting past + // a Safepoint instead of the memory edge. (An unfortunate consequence of having + // Safepoints not set Raw Memory; itself an unfortunate consequence of having Nodes + // which produce results (new raw memory state) inside of loops preventing all + // manner of other optimizations). Basically, it's ugly but so is the alternative. + // See comment in macro.cpp, around line 125 expand_allocate_common(). + virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } + }; //------------------------------LoadBNode-------------------------------------- @@ -370,16 +381,6 @@ virtual uint ideal_reg() const { return Op_RegP; } virtual int store_Opcode() const { return Op_StoreP; } virtual BasicType memory_type() const { return T_ADDRESS; } - // depends_only_on_test is almost always true, and needs to be almost always - // true to enable key hoisting & commoning optimizations. However, for the - // special case of RawPtr loads from TLS top & end, the control edge carries - // the dependence preventing hoisting past a Safepoint instead of the memory - // edge. (An unfortunate consequence of having Safepoints not set Raw - // Memory; itself an unfortunate consequence of having Nodes which produce - // results (new raw memory state) inside of loops preventing all manner of - // other optimizations). Basically, it's ugly but so is the alternative. - // See comment in macro.cpp, around line 125 expand_allocate_common(). - virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } }; @@ -393,16 +394,6 @@ virtual uint ideal_reg() const { return Op_RegN; } virtual int store_Opcode() const { return Op_StoreN; } virtual BasicType memory_type() const { return T_NARROWOOP; } - // depends_only_on_test is almost always true, and needs to be almost always - // true to enable key hoisting & commoning optimizations. However, for the - // special case of RawPtr loads from TLS top & end, the control edge carries - // the dependence preventing hoisting past a Safepoint instead of the memory - // edge. (An unfortunate consequence of having Safepoints not set Raw - // Memory; itself an unfortunate consequence of having Nodes which produce - // results (new raw memory state) inside of loops preventing all manner of - // other optimizations). Basically, it's ugly but so is the alternative. - // See comment in macro.cpp, around line 125 expand_allocate_common(). - virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } }; //------------------------------LoadKlassNode---------------------------------- diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/postaloc.cpp --- a/src/share/vm/opto/postaloc.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/postaloc.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -97,7 +97,8 @@ static bool expected_yanked_node(Node *old, Node *orig_old) { // This code is expected only next original nodes: // - load from constant table node which may have next data input nodes: - // MachConstantBase, Phi, MachTemp, MachSpillCopy + // MachConstantBase, MachTemp, MachSpillCopy + // - Phi nodes that are considered Junk // - load constant node which may have next data input nodes: // MachTemp, MachSpillCopy // - MachSpillCopy @@ -112,7 +113,9 @@ return (old == orig_old); } else if (old->is_MachTemp()) { return orig_old->is_Con(); - } else if (old->is_Phi() || old->is_MachConstantBase()) { + } else if (old->is_Phi()) { // Junk phi's + return true; + } else if (old->is_MachConstantBase()) { return (orig_old->is_Con() && orig_old->is_MachConstant()); } return false; @@ -522,11 +525,9 @@ u = u ? NodeSentinel : x; // Capture unique input, or NodeSentinel for 2nd input } if (u != NodeSentinel) { // Junk Phi. Remove - block->remove_node(j--); + phi->replace_by(u); + j -= yank_if_dead(phi, block, &value, ®nd); phi_dex--; - _cfg.unmap_node_from_block(phi); - phi->replace_by(u); - phi->disconnect_inputs(NULL, C); continue; } // Note that if value[pidx] exists, then we merged no new values here diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/type.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -2787,13 +2787,11 @@ //-----------------------------filter------------------------------------------ // Do not allow interface-vs.-noninterface joins to collapse to top. -const Type *TypeOopPtr::filter( const Type *kills ) const { +const Type *TypeOopPtr::filter(const Type *kills) const { const Type* ft = join(kills); const TypeInstPtr* ftip = ft->isa_instptr(); const TypeInstPtr* ktip = kills->isa_instptr(); - const TypeKlassPtr* ftkp = ft->isa_klassptr(); - const TypeKlassPtr* ktkp = kills->isa_klassptr(); if (ft->empty()) { // Check for evil case of 'this' being a class and 'kills' expecting an @@ -2807,8 +2805,6 @@ // uplift the type. if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) return kills; // Uplift to interface - if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface()) - return kills; // Uplift to interface return Type::TOP; // Canonical empty value } @@ -2825,14 +2821,6 @@ assert(!ftip->klass_is_exact(), "interface could not be exact"); return ktip->cast_to_ptr_type(ftip->ptr()); } - // Interface klass type could be exact in opposite to interface type, - // return it here instead of incorrect Constant ptr J/L/Object (6894807). - if (ftkp != NULL && ktkp != NULL && - ftkp->is_loaded() && ftkp->klass()->is_interface() && - !ftkp->klass_is_exact() && // Keep exact interface klass - ktkp->is_loaded() && !ktkp->klass()->is_interface()) { - return ktkp->cast_to_ptr_type(ftkp->ptr()); - } return ft; } @@ -4385,6 +4373,33 @@ return (_offset == 0) && !below_centerline(_ptr); } +// Do not allow interface-vs.-noninterface joins to collapse to top. +const Type *TypeKlassPtr::filter(const Type *kills) const { + // logic here mirrors the one from TypeOopPtr::filter. See comments + // there. + const Type* ft = join(kills); + const TypeKlassPtr* ftkp = ft->isa_klassptr(); + const TypeKlassPtr* ktkp = kills->isa_klassptr(); + + if (ft->empty()) { + if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface()) + return kills; // Uplift to interface + + return Type::TOP; // Canonical empty value + } + + // Interface klass type could be exact in opposite to interface type, + // return it here instead of incorrect Constant ptr J/L/Object (6894807). + if (ftkp != NULL && ktkp != NULL && + ftkp->is_loaded() && ftkp->klass()->is_interface() && + !ftkp->klass_is_exact() && // Keep exact interface klass + ktkp->is_loaded() && !ktkp->klass()->is_interface()) { + return ktkp->cast_to_ptr_type(ftkp->ptr()); + } + + return ft; +} + //----------------------compute_klass------------------------------------------ // Compute the defining klass for this class ciKlass* TypeAryPtr::compute_klass(DEBUG_ONLY(bool verify)) const { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/opto/type.hpp --- a/src/share/vm/opto/type.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/opto/type.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -63,7 +63,7 @@ class TypeOopPtr; class TypeInstPtr; class TypeAryPtr; -class TypeKlassPtr; +class TypeKlassPtr; class TypeMetadataPtr; //------------------------------Type------------------------------------------- @@ -1202,6 +1202,9 @@ 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 diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/prims/jvmtiGetLoadedClasses.cpp --- a/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -29,8 +29,43 @@ #include "runtime/thread.hpp" +// The closure for GetLoadedClasses +class LoadedClassesClosure : public KlassClosure { +private: + Stack _classStack; + JvmtiEnv* _env; -// The closure for GetLoadedClasses and GetClassLoaderClasses +public: + LoadedClassesClosure(JvmtiEnv* env) { + _env = env; + } + + void do_klass(Klass* k) { + // Collect all jclasses + _classStack.push((jclass) _env->jni_reference(k->java_mirror())); + } + + int extract(jclass* result_list) { + // The size of the Stack will be 0 after extract, so get it here + int count = (int)_classStack.size(); + int i = count; + + // Pop all jclasses, fill backwards + while (!_classStack.is_empty()) { + result_list[--i] = _classStack.pop(); + } + + // Return the number of elements written + return count; + } + + // Return current size of the Stack + int get_count() { + return (int)_classStack.size(); + } +}; + +// The closure for GetClassLoaderClasses class JvmtiGetLoadedClassesClosure : public StackObj { // Since the SystemDictionary::classes_do callback // doesn't pass a closureData pointer, @@ -165,19 +200,6 @@ } } - // Finally, the static methods that are the callbacks - static void increment(Klass* k) { - JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); - if (that->get_initiatingLoader() == NULL) { - for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - that->set_count(that->get_count() + 1); - } - } else if (k != NULL) { - // if initiating loader not null, just include the instance with 1 dimension - that->set_count(that->get_count() + 1); - } - } - static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) { JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); oop class_loader = loader_data->class_loader(); @@ -196,24 +218,6 @@ } } - static void add(Klass* k) { - JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); - if (that->available()) { - if (that->get_initiatingLoader() == NULL) { - for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { - oop mirror = l->java_mirror(); - that->set_element(that->get_index(), mirror); - that->set_index(that->get_index() + 1); - } - } else if (k != NULL) { - // if initiating loader not null, just include the instance with 1 dimension - oop mirror = k->java_mirror(); - that->set_element(that->get_index(), mirror); - that->set_index(that->get_index() + 1); - } - } - } - static void add_with_loader(Klass* k, ClassLoaderData* loader_data) { JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); if (that->available()) { @@ -255,39 +259,30 @@ jvmtiError JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) { - // Since SystemDictionary::classes_do only takes a function pointer - // and doesn't call back with a closure data pointer, - // we can only pass static methods. - JvmtiGetLoadedClassesClosure closure; + LoadedClassesClosure closure(env); { // To get a consistent list of classes we need MultiArray_lock to ensure - // array classes aren't created, and SystemDictionary_lock to ensure that - // classes aren't added to the system dictionary, + // array classes aren't created. MutexLocker ma(MultiArray_lock); - MutexLocker sd(SystemDictionary_lock); + + // Iterate through all classes in ClassLoaderDataGraph + // and collect them using the LoadedClassesClosure + ClassLoaderDataGraph::loaded_classes_do(&closure); + } - // First, count the classes - SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment); - Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment); - // Next, fill in the classes - closure.allocate(); - SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add); - Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add); - // Drop the SystemDictionary_lock, so the results could be wrong from here, - // but we still have a snapshot. + // Return results by extracting the collected contents into a list + // allocated via JvmtiEnv + jclass* result_list; + jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass), + (unsigned char**)&result_list); + + if (error == JVMTI_ERROR_NONE) { + int count = closure.extract(result_list); + *classCountPtr = count; + *classesPtr = result_list; } - // Post results - jclass* result_list; - jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass), - (unsigned char**)&result_list); - if (err != JVMTI_ERROR_NONE) { - return err; - } - closure.extract(env, result_list); - *classCountPtr = closure.get_count(); - *classesPtr = result_list; - return JVMTI_ERROR_NONE; + return error; } jvmtiError diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/prims/jvmtiImpl.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -210,6 +210,14 @@ } } +void GrowableCache::metadata_do(void f(Metadata*)) { + int len = _elements->length(); + for (int i=0; iat(i); + e->metadata_do(f); + } +} + void GrowableCache::gc_epilogue() { int len = _elements->length(); for (int i=0; imethod_holder()->class_loader_data()->class_loader(); + _class_holder = _method->method_holder()->klass_holder(); #ifdef CHECK_UNHANDLED_OOPS - // _class_loader can't be wrapped in a Handle, because JvmtiBreakpoint:s are - // eventually allocated on the heap. + // _class_holder can't be wrapped in a Handle, because JvmtiBreakpoints are + // sometimes allocated on the heap. // - // The code handling JvmtiBreakpoint:s allocated on the stack can't be - // interrupted by a GC until _class_loader is reachable by the GC via the + // The code handling JvmtiBreakpoints allocated on the stack can't be + // interrupted by a GC until _class_holder is reachable by the GC via the // oops_do method. - Thread::current()->allow_unhandled_oop(&_class_loader); + Thread::current()->allow_unhandled_oop(&_class_holder); #endif // CHECK_UNHANDLED_OOPS assert(_method != NULL, "_method != NULL"); _bci = (int) location; @@ -247,7 +255,7 @@ void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) { _method = bp._method; _bci = bp._bci; - _class_loader = bp._class_loader; + _class_holder = bp._class_holder; } bool JvmtiBreakpoint::lessThan(JvmtiBreakpoint& bp) { @@ -365,6 +373,13 @@ } } +void VM_ChangeBreakpoints::metadata_do(void f(Metadata*)) { + // Walk metadata in breakpoints to keep from being deallocated with RedefineClasses + if (_bp != NULL) { + _bp->metadata_do(f); + } +} + // // class JvmtiBreakpoints // @@ -381,6 +396,10 @@ _bps.oops_do(f); } +void JvmtiBreakpoints::metadata_do(void f(Metadata*)) { + _bps.metadata_do(f); +} + void JvmtiBreakpoints::gc_epilogue() { _bps.gc_epilogue(); } @@ -499,6 +518,12 @@ } } +void JvmtiCurrentBreakpoints::metadata_do(void f(Metadata*)) { + if (_jvmti_breakpoints != NULL) { + _jvmti_breakpoints->metadata_do(f); + } +} + void JvmtiCurrentBreakpoints::gc_epilogue() { if (_jvmti_breakpoints != NULL) { _jvmti_breakpoints->gc_epilogue(); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/prims/jvmtiImpl.hpp --- a/src/share/vm/prims/jvmtiImpl.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/prims/jvmtiImpl.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -69,6 +69,7 @@ virtual bool lessThan(GrowableElement *e)=0; virtual GrowableElement *clone() =0; virtual void oops_do(OopClosure* f) =0; + virtual void metadata_do(void f(Metadata*)) =0; }; class GrowableCache VALUE_OBJ_CLASS_SPEC { @@ -115,6 +116,8 @@ void clear(); // apply f to every element and update the cache void oops_do(OopClosure* f); + // walk metadata to preserve for RedefineClasses + void metadata_do(void f(Metadata*)); // update the cache after a full gc void gc_epilogue(); }; @@ -148,6 +151,7 @@ void remove (int index) { _cache.remove(index); } void clear() { _cache.clear(); } void oops_do(OopClosure* f) { _cache.oops_do(f); } + void metadata_do(void f(Metadata*)) { _cache.metadata_do(f); } void gc_epilogue() { _cache.gc_epilogue(); } }; @@ -169,7 +173,7 @@ Method* _method; int _bci; Bytecodes::Code _orig_bytecode; - oop _class_loader; + oop _class_holder; // keeps _method memory from being deallocated public: JvmtiBreakpoint(); @@ -191,9 +195,15 @@ bool lessThan(GrowableElement* e) { Unimplemented(); return false; } bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); } void oops_do(OopClosure* f) { - // Mark the method loader as live - f->do_oop(&_class_loader); + // Mark the method loader as live so the Method* class loader doesn't get + // unloaded and Method* memory reclaimed. + f->do_oop(&_class_holder); } + void metadata_do(void f(Metadata*)) { + // walk metadata to preserve for RedefineClasses + f(_method); + } + GrowableElement *clone() { JvmtiBreakpoint *bp = new JvmtiBreakpoint(); bp->copy(*this); @@ -239,6 +249,7 @@ int length(); void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); void print(); int set(JvmtiBreakpoint& bp); @@ -288,6 +299,7 @@ static inline bool is_breakpoint(address bcp); static void oops_do(OopClosure* f); + static void metadata_do(void f(Metadata*)); static void gc_epilogue(); }; @@ -332,6 +344,7 @@ VMOp_Type type() const { return VMOp_ChangeBreakpoints; } void doit(); void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); }; diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/prims/whitebox.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -53,6 +53,8 @@ #include "compiler/compileBroker.hpp" #include "runtime/compilationPolicy.hpp" +#define SIZE_T_MAX_VALUE ((size_t) -1) + bool WhiteBox::_used = false; WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) @@ -105,10 +107,116 @@ 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, p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(), - p->min_alignment(), p->max_alignment()); + p->space_alignment(), p->heap_alignment()); } WB_END +#ifndef PRODUCT +// Forward declaration +void TestReservedSpace_test(); +void TestReserveMemorySpecial_test(); +void TestVirtualSpace_test(); +void TestMetaspaceAux_test(); +#endif + +WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o)) +#ifndef PRODUCT + TestReservedSpace_test(); + TestReserveMemorySpecial_test(); + TestVirtualSpace_test(); + TestMetaspaceAux_test(); +#endif +WB_END + +WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o)) + size_t granularity = os::vm_allocation_granularity(); + ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL); + VirtualSpace vs; + vs.initialize(rhs, 50 * granularity); + + //Check if constraints are complied + if (!( UseCompressedOops && rhs.base() != NULL && + Universe::narrow_oop_base() != NULL && + Universe::narrow_oop_use_implicit_null_checks() )) { + tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n " + "\tUseCompressedOops is %d\n" + "\trhs.base() is "PTR_FORMAT"\n" + "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n" + "\tUniverse::narrow_oop_use_implicit_null_checks() is %d", + UseCompressedOops, + rhs.base(), + Universe::narrow_oop_base(), + Universe::narrow_oop_use_implicit_null_checks()); + return; + } + tty->print_cr("Reading from no access area... "); + tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c", + *(vs.low_boundary() - rhs.noaccess_prefix() / 2 )); +WB_END + +static jint wb_stress_virtual_space_resize(size_t reserved_space_size, + size_t magnitude, size_t iterations) { + size_t granularity = os::vm_allocation_granularity(); + ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL); + VirtualSpace vs; + if (!vs.initialize(rhs, 0)) { + tty->print_cr("Failed to initialize VirtualSpace. Can't proceed."); + return 3; + } + + long seed = os::random(); + tty->print_cr("Random seed is %ld", seed); + os::init_random(seed); + + for (size_t i = 0; i < iterations; i++) { + + // Whether we will shrink or grow + bool shrink = os::random() % 2L == 0; + + // Get random delta to resize virtual space + size_t delta = (size_t)os::random() % magnitude; + + // If we are about to shrink virtual space below zero, then expand instead + if (shrink && vs.committed_size() < delta) { + shrink = false; + } + + // Resizing by delta + if (shrink) { + vs.shrink_by(delta); + } else { + // If expanding fails expand_by will silently return false + vs.expand_by(delta, true); + } + } + return 0; +} + +WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o, + jlong reserved_space_size, jlong magnitude, jlong iterations)) + tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", " + "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude, + iterations); + if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) { + tty->print_cr("One of variables printed above is negative. Can't proceed.\n"); + return 1; + } + + // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is + // always 8 byte. That's why we should avoid overflow in case of 32bit platform. + if (sizeof(size_t) < sizeof(jlong)) { + jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE; + if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value + || iterations > size_t_max_value) { + tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n"); + return 2; + } + } + + return wb_stress_virtual_space_resize((size_t) reserved_space_size, + (size_t) magnitude, (size_t) iterations); +WB_END + #if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); @@ -445,6 +553,9 @@ {CC"getCompressedOopsMaxHeapSize", CC"()J", (void*)&WB_GetCompressedOopsMaxHeapSize}, {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, + {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests}, + {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea}, + {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize}, #if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/arguments.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1132,9 +1132,6 @@ Tier3InvokeNotifyFreqLog = 0; Tier4InvocationThreshold = 0; } - if (FLAG_IS_DEFAULT(NmethodSweepFraction)) { - FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M)); - } } #if INCLUDE_ALL_GCS @@ -1408,7 +1405,7 @@ // NULL page is located before the heap, we pad the NULL page to the conservative // maximum alignment that the GC may ever impose upon the heap. size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(), - Arguments::conservative_max_heap_alignment()); + _conservative_max_heap_alignment); LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page); NOT_LP64(ShouldNotReachHere(); return 0); @@ -1505,7 +1502,7 @@ } #endif // INCLUDE_ALL_GCS _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(), - CollectorPolicy::compute_max_alignment()); + CollectorPolicy::compute_heap_alignment()); } void Arguments::set_ergonomics_flags() { @@ -1988,6 +1985,15 @@ warning("DefaultMaxRAMFraction is deprecated and will likely be removed in a future release. " "Use MaxRAMFraction instead."); } + if (FLAG_IS_CMDLINE(UseCMSCompactAtFullCollection)) { + warning("UseCMSCompactAtFullCollection is deprecated and will likely be removed in a future release."); + } + if (FLAG_IS_CMDLINE(CMSFullGCsBeforeCompaction)) { + warning("CMSFullGCsBeforeCompaction is deprecated and will likely be removed in a future release."); + } + if (FLAG_IS_CMDLINE(UseCMSCollectionPassing)) { + warning("UseCMSCollectionPassing is deprecated and will likely be removed in a future release."); + } } // Check stack pages settings @@ -2156,6 +2162,10 @@ #if INCLUDE_ALL_GCS if (UseG1GC) { + status = status && verify_percentage(G1NewSizePercent, "G1NewSizePercent"); + status = status && verify_percentage(G1MaxNewSizePercent, "G1MaxNewSizePercent"); + status = status && verify_interval(G1NewSizePercent, 0, G1MaxNewSizePercent, "G1NewSizePercent"); + status = status && verify_percentage(InitiatingHeapOccupancyPercent, "InitiatingHeapOccupancyPercent"); status = status && verify_min_value(G1RefProcDrainInterval, 1, @@ -2672,9 +2682,10 @@ describe_range_error(errcode); return JNI_EINVAL; } - FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size); + set_min_heap_size((uintx)long_initial_heap_size); // Currently the minimum size and the initial heap sizes are the same. - set_min_heap_size(InitialHeapSize); + // Can be overridden with -XX:InitialHeapSize. + FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size); // -Xmx } else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) { julong long_max_heap_size = 0; @@ -3634,6 +3645,11 @@ "Incompatible compilation policy selected", NULL); } } + // Set NmethodSweepFraction after the size of the code cache is adapted (in case of tiered) + if (FLAG_IS_DEFAULT(NmethodSweepFraction)) { + FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M)); + } + // Set heap size based on available physical memory set_heap_size(); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/globals.cpp --- a/src/share/vm/runtime/globals.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/globals.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -321,6 +321,8 @@ { KIND_PRODUCT, "product" }, { KIND_MANAGEABLE, "manageable" }, { KIND_DIAGNOSTIC, "diagnostic" }, + { KIND_EXPERIMENTAL, "experimental" }, + { KIND_COMMERCIAL, "commercial" }, { KIND_NOT_PRODUCT, "notproduct" }, { KIND_DEVELOP, "develop" }, { KIND_LP64_PRODUCT, "lp64_product" }, diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/globals.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -2954,6 +2954,9 @@ product(intx, MaxRecursiveInlineLevel, 1, \ "maximum number of nested recursive calls that are inlined") \ \ + develop(intx, MaxForceInlineLevel, 100, \ + "maximum number of nested @ForceInline calls that are inlined") \ + \ product_pd(intx, InlineSmallCode, \ "Only inline already compiled methods if their code size is " \ "less than this") \ @@ -3019,9 +3022,6 @@ notproduct(intx, ZombieALotInterval, 5, \ "Number of exits until ZombieALot kicks in") \ \ - develop(bool, StressNonEntrant, false, \ - "Mark nmethods non-entrant at registration") \ - \ diagnostic(intx, MallocVerifyInterval, 0, \ "If non-zero, verify C heap after every N calls to " \ "malloc/realloc/free") \ @@ -3289,7 +3289,7 @@ "Exit the VM if we fill the code cache") \ \ product(bool, UseCodeCacheFlushing, true, \ - "Attempt to clean the code cache before shutting off compiler") \ + "Remove cold/old nmethods from the code cache") \ \ /* interpreter debugging */ \ develop(intx, BinarySwitchThreshold, 5, \ @@ -3622,9 +3622,6 @@ "Temporary flag for transition to AbstractMethodError wrapped " \ "in InvocationTargetException. See 6531596") \ \ - develop(bool, VerifyLambdaBytecodes, false, \ - "Force verification of jdk 8 lambda metafactory bytecodes") \ - \ develop(intx, FastSuperclassLimit, 8, \ "Depth of hardwired instanceof accelerator array") \ \ diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/handles.cpp --- a/src/share/vm/runtime/handles.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/handles.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -45,7 +45,7 @@ oop* HandleArea::allocate_handle(oop obj) { assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark"); assert(_no_handle_mark_nesting == 0, "allocating handle inside NoHandleMark"); - assert(obj->is_oop(), "sanity check"); + assert(obj->is_oop(), err_msg("not an oop: " INTPTR_FORMAT, (intptr_t*) obj)); return real_allocate_handle(obj); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/reflection.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -470,12 +470,6 @@ return true; } - // Also allow all accesses from - // java/lang/invoke/MagicLambdaImpl subclasses to succeed trivially. - if (current_class->is_subclass_of(SystemDictionary::lambda_MagicLambdaImpl_klass())) { - return true; - } - return can_relax_access_check_for(current_class, new_class, classloader_only); } @@ -570,12 +564,6 @@ return true; } - // Also allow all accesses from - // java/lang/invoke/MagicLambdaImpl subclasses to succeed trivially. - if (current_class->is_subclass_of(SystemDictionary::lambda_MagicLambdaImpl_klass())) { - return true; - } - return can_relax_access_check_for( current_class, field_class, classloader_only); } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -84,6 +84,7 @@ // Shared stub locations RuntimeStub* SharedRuntime::_wrong_method_blob; +RuntimeStub* SharedRuntime::_wrong_method_abstract_blob; RuntimeStub* SharedRuntime::_ic_miss_blob; RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; @@ -101,11 +102,12 @@ //----------------------------generate_stubs----------------------------------- void SharedRuntime::generate_stubs() { - _wrong_method_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method), "wrong_method_stub"); - _ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub"); - _resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call"); - _resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call"); - _resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call"); + _wrong_method_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method), "wrong_method_stub"); + _wrong_method_abstract_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_abstract), "wrong_method_abstract_stub"); + _ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub"); + _resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call"); + _resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call"); + _resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call"); #ifdef COMPILER2 // Vectors are generated only by C2. @@ -1345,6 +1347,11 @@ return callee_method->verified_code_entry(); JRT_END +// Handle abstract method call +JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_abstract(JavaThread* thread)) + return StubRoutines::throw_AbstractMethodError_entry(); +JRT_END + // resolve a static call and patch code JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_static_call_C(JavaThread *thread )) @@ -2341,12 +2348,13 @@ // Create a special handler for abstract methods. Abstract methods // are never compiled so an i2c entry is somewhat meaningless, but - // fill it in with something appropriate just in case. Pass handle - // wrong method for the c2i transitions. - address wrong_method = SharedRuntime::get_handle_wrong_method_stub(); + // throw AbstractMethodError just in case. + // Pass wrong_method_abstract for the c2i transitions to return + // AbstractMethodError for invalid invocations. + address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub(); _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL), StubRoutines::throw_AbstractMethodError_entry(), - wrong_method, wrong_method); + wrong_method_abstract, wrong_method_abstract); } AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint, diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/sharedRuntime.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -56,6 +56,7 @@ // Shared stub locations static RuntimeStub* _wrong_method_blob; + static RuntimeStub* _wrong_method_abstract_blob; static RuntimeStub* _ic_miss_blob; static RuntimeStub* _resolve_opt_virtual_call_blob; static RuntimeStub* _resolve_virtual_call_blob; @@ -206,6 +207,11 @@ return _wrong_method_blob->entry_point(); } + static address get_handle_wrong_method_abstract_stub() { + assert(_wrong_method_abstract_blob!= NULL, "oops"); + return _wrong_method_abstract_blob->entry_point(); + } + #ifdef COMPILER2 static void generate_uncommon_trap_blob(void); static UncommonTrapBlob* uncommon_trap_blob() { return _uncommon_trap_blob; } @@ -481,6 +487,7 @@ // handle ic miss with caller being compiled code // wrong method handling (inline cache misses, zombie methods) static address handle_wrong_method(JavaThread* thread); + static address handle_wrong_method_abstract(JavaThread* thread); static address handle_wrong_method_ic_miss(JavaThread* thread); #ifndef PRODUCT diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/sweeper.cpp --- a/src/share/vm/runtime/sweeper.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/sweeper.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -112,14 +112,13 @@ if (_records != NULL) { _records[_sweep_index].traversal = _traversals; _records[_sweep_index].traversal_mark = nm->_stack_traversal_mark; - _records[_sweep_index].invocation = _invocations; + _records[_sweep_index].invocation = _sweep_fractions_left; _records[_sweep_index].compile_id = nm->compile_id(); _records[_sweep_index].kind = nm->compile_kind(); _records[_sweep_index].state = nm->_state; _records[_sweep_index].vep = nm->verified_entry_point(); _records[_sweep_index].uep = nm->entry_point(); _records[_sweep_index].line = line; - _sweep_index = (_sweep_index + 1) % SweeperLogEntries; } } @@ -127,26 +126,29 @@ #define SWEEP(nm) #endif -nmethod* NMethodSweeper::_current = NULL; // Current nmethod -long NMethodSweeper::_traversals = 0; // Nof. stack traversals performed -int NMethodSweeper::_seen = 0; // Nof. nmethods we have currently processed in current pass of CodeCache -int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep -int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep -int NMethodSweeper::_marked_count = 0; // Nof. nmethods marked for reclaim in current sweep - -volatile int NMethodSweeper::_invocations = 0; // Nof. invocations left until we are completed with this pass -volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress. +nmethod* NMethodSweeper::_current = NULL; // Current nmethod +long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. +long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper +long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened +int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache +int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep +int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep +int NMethodSweeper::_marked_for_reclamation_count = 0; // Nof. nmethods marked for reclaim in current sweep -jint NMethodSweeper::_locked_seen = 0; -jint NMethodSweeper::_not_entrant_seen_on_stack = 0; -bool NMethodSweeper::_request_mark_phase = false; +volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper +volatile int NMethodSweeper::_sweep_fractions_left = 0; // Nof. invocations left until we are completed with this pass +volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper +volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: + // 1) alive -> not_entrant + // 2) not_entrant -> zombie + // 3) zombie -> marked_for_reclamation -int NMethodSweeper::_total_nof_methods_reclaimed = 0; -jlong NMethodSweeper::_total_time_sweeping = 0; -jlong NMethodSweeper::_total_time_this_sweep = 0; -jlong NMethodSweeper::_peak_sweep_time = 0; -jlong NMethodSweeper::_peak_sweep_fraction_time = 0; -int NMethodSweeper::_hotness_counter_reset_val = 0; +int NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed +jlong NMethodSweeper::_total_time_sweeping = 0; // Accumulated time sweeping +jlong NMethodSweeper::_total_time_this_sweep = 0; // Total time this sweep +jlong NMethodSweeper::_peak_sweep_time = 0; // Peak time for a full sweep +jlong NMethodSweeper::_peak_sweep_fraction_time = 0; // Peak time sweeping one fraction +int NMethodSweeper::_hotness_counter_reset_val = 0; class MarkActivationClosure: public CodeBlobClosure { @@ -197,13 +199,16 @@ return; } + // Increase time so that we can estimate when to invoke the sweeper again. + _time_counter++; + // Check for restart assert(CodeCache::find_blob_unsafe(_current) == _current, "Sweeper nmethod cached state invalid"); - if (!sweep_in_progress() && need_marking_phase()) { - _seen = 0; - _invocations = NmethodSweepFraction; - _current = CodeCache::first_nmethod(); - _traversals += 1; + if (!sweep_in_progress()) { + _seen = 0; + _sweep_fractions_left = NmethodSweepFraction; + _current = CodeCache::first_nmethod(); + _traversals += 1; _total_time_this_sweep = 0; if (PrintMethodFlushing) { @@ -211,10 +216,6 @@ } Threads::nmethods_do(&mark_activation_closure); - // reset the flags since we started a scan from the beginning. - reset_nmethod_marking(); - _locked_seen = 0; - _not_entrant_seen_on_stack = 0; } else { // Only set hotness counter Threads::nmethods_do(&set_hotness_closure); @@ -222,14 +223,49 @@ OrderAccess::storestore(); } - +/** + * This function invokes the sweeper if at least one of the three conditions is met: + * (1) The code cache is getting full + * (2) There are sufficient state changes in/since the last sweep. + * (3) We have not been sweeping for 'some time' + */ void NMethodSweeper::possibly_sweep() { assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode"); - if (!MethodFlushing || !sweep_in_progress()) { + // Only compiler threads are allowed to sweep + if (!MethodFlushing || !sweep_in_progress() || !Thread::current()->is_Compiler_thread()) { return; } - if (_invocations > 0) { + // If there was no state change while nmethod sweeping, 'should_sweep' will be false. + // This is one of the two places where should_sweep can be set to true. The general + // idea is as follows: If there is enough free space in the code cache, there is no + // need to invoke the sweeper. The following formula (which determines whether to invoke + // the sweeper or not) depends on the assumption that for larger ReservedCodeCacheSizes + // we need less frequent sweeps than for smaller ReservedCodecCacheSizes. Furthermore, + // the formula considers how much space in the code cache is currently used. Here are + // some examples that will (hopefully) help in understanding. + // + // Small ReservedCodeCacheSizes: (e.g., < 16M) We invoke the sweeper every time, since + // the result of the division is 0. This + // keeps the used code cache size small + // (important for embedded Java) + // Large ReservedCodeCacheSize : (e.g., 256M + code cache is 10% full). The formula + // computes: (256 / 16) - 1 = 15 + // As a result, we invoke the sweeper after + // 15 invocations of 'mark_active_nmethods. + // Large ReservedCodeCacheSize: (e.g., 256M + code Cache is 90% full). The formula + // computes: (256 / 16) - 10 = 6. + if (!_should_sweep) { + int time_since_last_sweep = _time_counter - _last_sweep; + double wait_until_next_sweep = (ReservedCodeCacheSize / (16 * M)) - time_since_last_sweep - + CodeCache::reverse_free_ratio(); + + if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) { + _should_sweep = true; + } + } + + if (_should_sweep && _sweep_fractions_left > 0) { // Only one thread at a time will sweep jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 ); if (old != 0) { @@ -242,31 +278,46 @@ memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries); } #endif - if (_invocations > 0) { + + if (_sweep_fractions_left > 0) { sweep_code_cache(); - _invocations--; + _sweep_fractions_left--; + } + + // We are done with sweeping the code cache once. + if (_sweep_fractions_left == 0) { + _last_sweep = _time_counter; + // Reset flag; temporarily disables sweeper + _should_sweep = false; + // If there was enough state change, 'possibly_enable_sweeper()' + // sets '_should_sweep' to true + possibly_enable_sweeper(); + // Reset _bytes_changed only if there was enough state change. _bytes_changed + // can further increase by calls to 'report_state_change'. + if (_should_sweep) { + _bytes_changed = 0; + } } _sweep_started = 0; } } void NMethodSweeper::sweep_code_cache() { - jlong sweep_start_counter = os::elapsed_counter(); - _flushed_count = 0; - _zombified_count = 0; - _marked_count = 0; + _flushed_count = 0; + _zombified_count = 0; + _marked_for_reclamation_count = 0; if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations); + tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left); } if (!CompileBroker::should_compile_new_jobs()) { // If we have turned off compilations we might as well do full sweeps // in order to reach the clean state faster. Otherwise the sleeping compiler // threads will slow down sweeping. - _invocations = 1; + _sweep_fractions_left = 1; } // We want to visit all nmethods after NmethodSweepFraction @@ -274,7 +325,7 @@ // remaining number of invocations. This is only an estimate since // the number of nmethods changes during the sweep so the final // stage must iterate until it there are no more nmethods. - int todo = (CodeCache::nof_nmethods() - _seen) / _invocations; + int todo = (CodeCache::nof_nmethods() - _seen) / _sweep_fractions_left; int swept_count = 0; @@ -286,11 +337,11 @@ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); // The last invocation iterates until there are no more nmethods - for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) { + for (int i = 0; (i < todo || _sweep_fractions_left == 1) && _current != NULL; i++) { swept_count++; if (SafepointSynchronize::is_synchronizing()) { // Safepoint request if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _invocations); + tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left); } MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); @@ -314,19 +365,7 @@ } } - assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache"); - - if (!sweep_in_progress() && !need_marking_phase() && (_locked_seen || _not_entrant_seen_on_stack)) { - // we've completed a scan without making progress but there were - // nmethods we were unable to process either because they were - // locked or were still on stack. We don't have to aggressively - // clean them up so just stop scanning. We could scan once more - // but that complicates the control logic and it's unlikely to - // matter much. - if (PrintMethodFlushing) { - tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep"); - } - } + assert(_sweep_fractions_left > 1 || _current == NULL, "must have scanned the whole cache"); jlong sweep_end_counter = os::elapsed_counter(); jlong sweep_time = sweep_end_counter - sweep_start_counter; @@ -340,21 +379,21 @@ event.set_starttime(sweep_start_counter); event.set_endtime(sweep_end_counter); event.set_sweepIndex(_traversals); - event.set_sweepFractionIndex(NmethodSweepFraction - _invocations + 1); + event.set_sweepFractionIndex(NmethodSweepFraction - _sweep_fractions_left + 1); event.set_sweptCount(swept_count); event.set_flushedCount(_flushed_count); - event.set_markedCount(_marked_count); + event.set_markedCount(_marked_for_reclamation_count); event.set_zombifiedCount(_zombified_count); event.commit(); } #ifdef ASSERT if(PrintMethodFlushing) { - tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time); + tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _sweep_fractions_left, (jlong)sweep_time); } #endif - if (_invocations == 1) { + if (_sweep_fractions_left == 1) { _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); log_sweep("finished"); } @@ -368,12 +407,37 @@ // it only makes sense to re-enable compilation if we have actually freed memory. // Note that typically several kB are released for sweeping 16MB of the code // cache. As a result, 'freed_memory' > 0 to restart the compiler. - if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0))) { + if (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0)) { CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation); log_sweep("restart_compiler"); } } +/** + * This function updates the sweeper statistics that keep track of nmethods + * state changes. If there is 'enough' state change, the sweeper is invoked + * as soon as possible. There can be data races on _bytes_changed. The data + * races are benign, since it does not matter if we loose a couple of bytes. + * In the worst case we call the sweeper a little later. Also, we are guaranteed + * to invoke the sweeper if the code cache gets full. + */ +void NMethodSweeper::report_state_change(nmethod* nm) { + _bytes_changed += nm->total_size(); + possibly_enable_sweeper(); +} + +/** + * Function determines if there was 'enough' state change in the code cache to invoke + * the sweeper again. Currently, we determine 'enough' as more than 1% state change in + * the code cache since the last sweep. + */ +void NMethodSweeper::possibly_enable_sweeper() { + double percent_changed = ((double)_bytes_changed / (double)ReservedCodeCacheSize) * 100; + if (percent_changed > 1.0) { + _should_sweep = true; + } +} + class NMethodMarker: public StackObj { private: CompilerThread* _thread; @@ -424,9 +488,6 @@ MutexLocker cl(CompiledIC_lock); nm->cleanup_inline_caches(); SWEEP(nm); - } else { - _locked_seen++; - SWEEP(nm); } return freed_memory; } @@ -448,8 +509,9 @@ tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); } nm->mark_for_reclamation(); - request_nmethod_marking(); - _marked_count++; + // Keep track of code cache state change + _bytes_changed += nm->total_size(); + _marked_for_reclamation_count++; SWEEP(nm); } } else if (nm->is_not_entrant()) { @@ -459,18 +521,14 @@ if (PrintMethodFlushing && Verbose) { tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); } + // Code cache state change is tracked in make_zombie() nm->make_zombie(); - request_nmethod_marking(); _zombified_count++; SWEEP(nm); } else { // Still alive, clean up its inline caches MutexLocker cl(CompiledIC_lock); nm->cleanup_inline_caches(); - // we coudn't transition this nmethod so don't immediately - // request a rescan. If this method stays on the stack for a - // long time we don't want to keep rescanning the code cache. - _not_entrant_seen_on_stack++; SWEEP(nm); } } else if (nm->is_unloaded()) { @@ -485,8 +543,8 @@ release_nmethod(nm); _flushed_count++; } else { + // Code cache state change is tracked in make_zombie() nm->make_zombie(); - request_nmethod_marking(); _zombified_count++; SWEEP(nm); } @@ -514,7 +572,11 @@ // The second condition ensures that methods are not immediately made not-entrant // after compilation. nm->make_not_entrant(); - request_nmethod_marking(); + // Code cache state change is tracked in make_not_entrant() + if (PrintMethodFlushing && Verbose) { + tty->print_cr("### Nmethod %d/" PTR_FORMAT "made not-entrant: hotness counter %d/%d threshold %f", + nm->compile_id(), nm, nm->hotness_counter(), reset_val, threshold); + } } } } diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/sweeper.hpp --- a/src/share/vm/runtime/sweeper.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/sweeper.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -53,22 +53,22 @@ // is full. class NMethodSweeper : public AllStatic { - static long _traversals; // Stack scan count, also sweep ID. - static nmethod* _current; // Current nmethod - static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache - static int _flushed_count; // Nof. nmethods flushed in current sweep - static int _zombified_count; // Nof. nmethods made zombie in current sweep - static int _marked_count; // Nof. nmethods marked for reclaim in current sweep + static long _traversals; // Stack scan count, also sweep ID. + static long _time_counter; // Virtual time used to periodically invoke sweeper + static long _last_sweep; // Value of _time_counter when the last sweep happened + static nmethod* _current; // Current nmethod + static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache + static int _flushed_count; // Nof. nmethods flushed in current sweep + static int _zombified_count; // Nof. nmethods made zombie in current sweep + static int _marked_for_reclamation_count; // Nof. nmethods marked for reclaim in current sweep - static volatile int _invocations; // No. of invocations left until we are completed with this pass - static volatile int _sweep_started; // Flag to control conc sweeper - - //The following are reset in mark_active_nmethods and synchronized by the safepoint - static bool _request_mark_phase; // Indicates that a change has happend and we need another mark pahse, - // always checked and reset at a safepoint so memory will be in sync. - static int _locked_seen; // Number of locked nmethods encountered during the scan - static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack - + static volatile int _sweep_fractions_left; // Nof. invocations left until we are completed with this pass + static volatile int _sweep_started; // Flag to control conc sweeper + static volatile bool _should_sweep; // Indicates if we should invoke the sweeper + static volatile int _bytes_changed; // Counts the total nmethod size if the nmethod changed from: + // 1) alive -> not_entrant + // 2) not_entrant -> zombie + // 3) zombie -> marked_for_reclamation // Stat counters static int _total_nof_methods_reclaimed; // Accumulated nof methods flushed static jlong _total_time_sweeping; // Accumulated time sweeping @@ -81,9 +81,6 @@ static bool sweep_in_progress(); static void sweep_code_cache(); - static void request_nmethod_marking() { _request_mark_phase = true; } - static void reset_nmethod_marking() { _request_mark_phase = false; } - static bool need_marking_phase() { return _request_mark_phase; } static int _hotness_counter_reset_val; @@ -109,13 +106,8 @@ static int sort_nmethods_by_hotness(nmethod** nm1, nmethod** nm2); static int hotness_counter_reset_val(); - - static void notify() { - // Request a new sweep of the code cache from the beginning. No - // need to synchronize the setting of this flag since it only - // changes to false at safepoint so we can never overwrite it with false. - request_nmethod_marking(); - } + static void report_state_change(nmethod* nm); + static void possibly_enable_sweeper(); }; #endif // SHARE_VM_RUNTIME_SWEEPER_HPP diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/runtime/thread.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1097,7 +1097,7 @@ // General purpose hook into Java code, run once when the VM is initialized. // The Java library method itself may be changed independently from the VM. static void call_postVMInitHook(TRAPS) { - Klass* k = SystemDictionary::PostVMInitHook_klass(); + Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_misc_PostVMInitHook(), THREAD); instanceKlassHandle klass (THREAD, k); if (klass.not_null()) { JavaValue result(T_VOID); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/services/jmm.h --- a/src/share/vm/services/jmm.h Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/services/jmm.h Tue Dec 03 14:13:06 2013 +0400 @@ -78,6 +78,7 @@ JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ + JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/services/management.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -1032,6 +1032,9 @@ case JMM_JVM_INIT_DONE_TIME_MS: return Management::vm_init_done_time(); + case JMM_JVM_UPTIME_MS: + return Management::ticks_to_ms(os::elapsed_counter()); + case JMM_COMPILE_TOTAL_TIME_MS: return Management::ticks_to_ms(CompileBroker::total_compilation_ticks()); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/services/threadService.cpp --- a/src/share/vm/services/threadService.cpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/services/threadService.cpp Tue Dec 03 14:13:06 2013 +0400 @@ -200,6 +200,12 @@ } } +void ThreadService::metadata_do(void f(Metadata*)) { + for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) { + dump->metadata_do(f); + } +} + void ThreadService::add_thread_dump(ThreadDumpResult* dump) { MutexLocker ml(Management_lock); if (_threaddump_list == NULL) { @@ -451,9 +457,16 @@ } } +void ThreadDumpResult::metadata_do(void f(Metadata*)) { + for (ThreadSnapshot* ts = _snapshots; ts != NULL; ts = ts->next()) { + ts->metadata_do(f); + } +} + StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) { _method = jvf->method(); _bci = jvf->bci(); + _class_holder = _method->method_holder()->klass_holder(); _locked_monitors = NULL; if (with_lock_info) { ResourceMark rm; @@ -477,6 +490,11 @@ f->do_oop((oop*) _locked_monitors->adr_at(i)); } } + f->do_oop(&_class_holder); +} + +void StackFrameInfo::metadata_do(void f(Metadata*)) { + f(_method); } void StackFrameInfo::print_on(outputStream* st) const { @@ -620,6 +638,14 @@ } } +void ThreadStackTrace::metadata_do(void f(Metadata*)) { + int length = _frames->length(); + for (int i = 0; i < length; i++) { + _frames->at(i)->metadata_do(f); + } +} + + ConcurrentLocksDump::~ConcurrentLocksDump() { if (_retain_map_on_free) { return; @@ -823,6 +849,13 @@ } } +void ThreadSnapshot::metadata_do(void f(Metadata*)) { + if (_stack_trace != NULL) { + _stack_trace->metadata_do(f); + } +} + + DeadlockCycle::DeadlockCycle() { _is_deadlock = false; _threads = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_ARRAY_SIZE, true); diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/services/threadService.hpp --- a/src/share/vm/services/threadService.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/services/threadService.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -113,6 +113,7 @@ // GC support static void oops_do(OopClosure* f); + static void metadata_do(void f(Metadata*)); }; // Per-thread Statistics for synchronization @@ -242,6 +243,7 @@ void dump_stack_at_safepoint(int max_depth, bool with_locked_monitors); void set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; } void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); }; class ThreadStackTrace : public CHeapObj { @@ -265,6 +267,7 @@ void dump_stack_at_safepoint(int max_depth); Handle allocate_fill_stack_trace_element_array(TRAPS); void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); GrowableArray* jni_locked_monitors() { return _jni_locked_monitors; } int num_jni_locked_monitors() { return (_jni_locked_monitors != NULL ? _jni_locked_monitors->length() : 0); } @@ -280,6 +283,9 @@ Method* _method; int _bci; GrowableArray* _locked_monitors; // list of object monitors locked by this frame + // We need to save the mirrors in the backtrace to keep the class + // from being unloaded while we still have this stack trace. + oop _class_holder; public: @@ -289,9 +295,10 @@ delete _locked_monitors; } }; - Method* method() const { return _method; } + Method* method() const { return _method; } int bci() const { return _bci; } void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); int num_locked_monitors() { return (_locked_monitors != NULL ? _locked_monitors->length() : 0); } GrowableArray* locked_monitors() { return _locked_monitors; } @@ -354,6 +361,7 @@ int num_snapshots() { return _num_snapshots; } ThreadSnapshot* snapshots() { return _snapshots; } void oops_do(OopClosure* f); + void metadata_do(void f(Metadata*)); }; class DeadlockCycle : public CHeapObj { diff -r c31f0cbe6d9e -r 0611ce949aaa src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Sun Nov 03 07:50:24 2013 +0000 +++ b/src/share/vm/utilities/globalDefinitions.hpp Tue Dec 03 14:13:06 2013 +0400 @@ -368,8 +368,6 @@ // Klass encoding metaspace max size const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlassAlignmentInBytes; -const jlong CompressedKlassPointersBase = NOT_LP64(0) LP64_ONLY(CONST64(0x800000000)); // 32*G - // Machine dependent stuff #ifdef TARGET_ARCH_x86 @@ -458,6 +456,13 @@ return (void*) align_size_up_((uintptr_t)addr, size); } +// Align down with a lower bound. If the aligning results in 0, return 'alignment'. + +inline size_t align_size_down_bounded(size_t size, size_t alignment) { + size_t aligned_size = align_size_down_(size, alignment); + return aligned_size > 0 ? aligned_size : alignment; +} + // Clamp an address to be within a specific page // 1. If addr is on the page it is returned as is // 2. If addr is above the page_address the start of the *next* page will be returned diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/inlining/InlineDefaultMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/inlining/InlineDefaultMethod.java Tue Dec 03 14:13:06 2013 +0400 @@ -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. + */ + +/* + * @test + * @bug 8026735 + * @summary CHA in C1 should make correct decisions about default methods + * @run main/othervm -Xcomp -XX:CompileOnly=InlineDefaultMethod::test -XX:TieredStopAtLevel=1 InlineDefaultMethod + */ + + +interface InterfaceWithDefaultMethod0 { + default public int defaultMethod() { + return 1; + } +} + +interface InterfaceWithDefaultMethod1 extends InterfaceWithDefaultMethod0 { } + +abstract class Subtype implements InterfaceWithDefaultMethod1 { } + +class Decoy extends Subtype { + public int defaultMethod() { + return 2; + } +} + +class Instance extends Subtype { } + +public class InlineDefaultMethod { + public static int test(InterfaceWithDefaultMethod1 x) { + return x.defaultMethod(); + } + public static void main(String[] args) { + InterfaceWithDefaultMethod1 a = new Decoy(); + InterfaceWithDefaultMethod1 b = new Instance(); + if (test(a) != 2 || + test(b) != 1) { + System.err.println("FAILED"); + System.exit(97); + } + System.err.println("PASSED"); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/CompareTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/mathexact/CompareTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8026722 + * @summary Verify that the compare after addExact is a signed compare + * @compile CompareTest.java + * @run main CompareTest + * + */ + +public class CompareTest { + public static long store = 0; + public static long addValue = 1231; + + public static void main(String[] args) { + for (int i = 0; i < 20000; ++i) { + runTest(i, i); + runTest(i-1, i); + } + } + + public static long create(long value, int v) { + if ((value | v) == 0) { + return 0; + } + + // C2 turned this test into unsigned test when a control edge was set on the Cmp + if (value < -31557014167219200L || value > 31556889864403199L) { + throw new RuntimeException("error"); + } + + return value; + } + + public static void runTest(long value, int value2) { + long res = Math.addExact(value, addValue); + store = create(res, Math.floorMod(value2, 100000)); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/GVNTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/mathexact/GVNTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,60 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8028207 + * @summary Verify that GVN doesn't mess up the two addExacts + * @compile GVNTest.java + * @run main GVNTest + * + */ + +public class GVNTest { + public static int result = 0; + public static int value = 93; + public static void main(String[] args) { + for (int i = 0; i < 50000; ++i) { + result = runTest(value + i); + result = runTest(value + i); + result = runTest(value + i); + result = runTest(value + i); + result = runTest(value + i); + } + } + + public static int runTest(int value) { + int v = value + value; + int sum = 0; + if (v < 4032) { + for (int i = 0; i < 1023; ++i) { + sum += Math.addExact(value, value); + } + } else { + for (int i = 0; i < 321; ++i) { + sum += Math.addExact(value, value); + } + } + return sum + v; + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/NestedMathExactTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/mathexact/NestedMathExactTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,54 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8027444 + * @summary Test nested loops + * @compile NestedMathExactTest.java + * @run main NestedMathExactTest + * + */ + +public class NestedMathExactTest { + public static final int LIMIT = 100; + public static int[] result = new int[LIMIT]; + public static int value = 17; + + public static void main(String[] args) { + for (int i = 0; i < 100; ++i) { + result[i] = runTest(); + } + } + + public static int runTest() { + int sum = 0; + for (int j = 0; j < 100000; j = Math.addExact(j, 1)) { + sum = 1; + for (int i = 0; i < 5; ++i) { + sum *= value; + } + } + return sum; + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/SplitThruPhiTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/mathexact/SplitThruPhiTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,50 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8028198 + * @summary Verify that split through phi does the right thing + * @compile SplitThruPhiTest.java + * @run main SplitThruPhiTest + * + */ + +public class SplitThruPhiTest { + public static volatile int value = 19; + public static int store = 0; + public static void main(String[] args) { + for (int i = 0; i < 150000; ++i) { + store = runTest(value); + } + } + + public static int runTest(int val) { + int result = Math.addExact(val, 1); + int total = 0; + for (int i = val; i < 200; i = Math.addExact(i, 1)) { + total += i; + } + return total; + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/SubExactLConstantTest.java --- a/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Sun Nov 03 07:50:24 2013 +0000 +++ b/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -24,6 +24,7 @@ /* * @test * @bug 8026844 + * @bug 8027353 * @summary Test constant subtractExact * @compile SubExactLConstantTest.java Verify.java * @run main SubExactLConstantTest diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java --- a/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Sun Nov 03 07:50:24 2013 +0000 +++ b/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -24,6 +24,7 @@ /* * @test * @bug 8026844 + * @bug 8027353 * @summary Test non constant subtractExact * @compile SubExactLNonConstantTest.java Verify.java * @run main SubExactLNonConstantTest diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/intrinsics/stringequals/TestStringEqualsBadLength.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/stringequals/TestStringEqualsBadLength.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,82 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8027445 + * @summary String.equals() may be called with a length whose upper bits are not cleared + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestStringEqualsBadLength + * + */ + +import java.util.Arrays; + +public class TestStringEqualsBadLength { + + int v1; + int v2; + + boolean m(String s1) { + int l = v2 - v1; // 0 - (-1) = 1. On 64 bit: 0xffffffff00000001 + char[] arr = new char[l]; + arr[0] = 'a'; + String s2 = new String(arr); + // The string length is not reloaded but the value computed is + // reused so pointer computation must not use + // 0xffffffff00000001 + return s2.equals(s1); + } + + // Same thing with String.compareTo() + int m2(String s1) { + int l = v2 - v1; + char[] arr = new char[l+1]; + arr[0] = 'a'; + arr[1] = 'b'; + String s2 = new String(arr); + return s2.compareTo(s1); + } + + // Same thing with equals() for arrays + boolean m3(char[] arr1) { + int l = v2 - v1; // 0 - (-1) = 1. On 64 bit: 0xffffffff00000001 + char[] arr2 = new char[l]; + arr2[0] = 'a'; + return Arrays.equals(arr2, arr1); + } + + static public void main(String[] args) { + TestStringEqualsBadLength tse = new TestStringEqualsBadLength(); + tse.v1 = -1; + tse.v2 = 0; + char[] arr = new char[1]; + arr[0] = 'a'; + for (int i = 0; i < 20000; i++) { + tse.m("a"); + tse.m2("ab"); + tse.m3(arr); + } + + System.out.println("TEST PASSED"); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/jsr292/ConcurrentClassLoadingTest.java --- a/test/compiler/jsr292/ConcurrentClassLoadingTest.java Sun Nov 03 07:50:24 2013 +0000 +++ b/test/compiler/jsr292/ConcurrentClassLoadingTest.java Tue Dec 03 14:13:06 2013 +0400 @@ -172,7 +172,6 @@ "java.lang.invoke.LambdaConversionException", "java.lang.invoke.LambdaForm", "java.lang.invoke.LambdaMetafactory", - "java.lang.invoke.MagicLambdaImpl", "java.lang.invoke.MemberName", "java.lang.invoke.MethodHandle", "java.lang.invoke.MethodHandleImpl", diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/profiling/TestUnexpectedProfilingMismatch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/profiling/TestUnexpectedProfilingMismatch.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,102 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8027631 + * @summary profiling of arguments at calls cannot rely on signature of callee for types + * @run main/othervm -XX:-BackgroundCompilation -XX:TieredStopAtLevel=3 -XX:TypeProfileLevel=111 -XX:Tier3InvocationThreshold=200 -XX:Tier0InvokeNotifyFreqLog=7 TestUnexpectedProfilingMismatch + * + */ + +import java.lang.invoke.*; + +public class TestUnexpectedProfilingMismatch { + + static class A { + } + + static class B { + } + + static void mA(A a) { + } + + static void mB(B b) { + } + + static final MethodHandle mhA; + static final MethodHandle mhB; + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(void.class, A.class); + MethodHandle res = null; + try { + res = lookup.findStatic(TestUnexpectedProfilingMismatch.class, "mA", mt); + } catch(NoSuchMethodException ex) { + } catch(IllegalAccessException ex) { + } + mhA = res; + mt = MethodType.methodType(void.class, B.class); + try { + res = lookup.findStatic(TestUnexpectedProfilingMismatch.class, "mB", mt); + } catch(NoSuchMethodException ex) { + } catch(IllegalAccessException ex) { + } + mhB = res; + } + + void m1(A a, boolean doit) throws Throwable { + if (doit) { + mhA.invoke(a); + } + } + + void m2(B b) throws Throwable { + mhB.invoke(b); + } + + static public void main(String[] args) { + TestUnexpectedProfilingMismatch tih = new TestUnexpectedProfilingMismatch(); + A a = new A(); + B b = new B(); + try { + for (int i = 0; i < 256 - 1; i++) { + tih.m1(a, true); + } + // Will trigger the compilation but will also run once + // more interpreted with a non null MDO which it will + // update. Make it skip the body of the method. + tih.m1(a, false); + // Compile this one as well and do the profiling + for (int i = 0; i < 256; i++) { + tih.m2(b); + } + // Will run and see a conflict + tih.m1(a, true); + } catch(Throwable ex) { + ex.printStackTrace(); + } + System.out.println("TEST PASSED"); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/profiling/unloadingconflict/B.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/profiling/unloadingconflict/B.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,25 @@ +/* + * 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. + */ + +public class B { +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/profiling/unloadingconflict/TestProfileConflictClassUnloading.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/profiling/unloadingconflict/TestProfileConflictClassUnloading.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,88 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8027572 + * @summary class unloading resets profile, method compiled after the profile is first set and before class loading sets unknown bit with not recorded class + * @build B + * @run main/othervm -XX:TypeProfileLevel=222 -XX:-BackgroundCompilation TestProfileConflictClassUnloading + * + */ + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Paths; + +public class TestProfileConflictClassUnloading { + static class A { + } + + + static void m1(Object o) { + } + + static void m2(Object o) { + m1(o); + } + + static void m3(A a, boolean do_call) { + if (!do_call) { + return; + } + m2(a); + } + + public static ClassLoader newClassLoader() { + try { + return new URLClassLoader(new URL[] { + Paths.get(System.getProperty("test.classes",".")).toUri().toURL(), + }, null); + } catch (MalformedURLException e){ + throw new RuntimeException("Unexpected URL conversion failure", e); + } + } + + public static void main(String[] args) throws Exception { + ClassLoader loader = newClassLoader(); + Object o = loader.loadClass("B").newInstance(); + // collect conflicting profiles + for (int i = 0; i < 5000; i++) { + m2(o); + } + // prepare for conflict + A a = new A(); + for (int i = 0; i < 5000; i++) { + m3(a, false); + } + // unload class in profile + o = null; + loader = null; + System.gc(); + // record the conflict + m3(a, true); + // trigger another GC + System.gc(); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/regalloc/C1ObjectSpillInLogicOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/regalloc/C1ObjectSpillInLogicOp.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8027751 + * @summary C1 crashes generating G1 post-barrier in Unsafe.getAndSetObject() intrinsic because of the new value spill + * @run main/othervm -XX:+UseG1GC C1ObjectSpillInLogicOp + * + * G1 barriers use logical operators (xor) on T_OBJECT mixed with T_LONG or T_INT. + * The current implementation of logical operations on x86 in C1 doesn't allow for long operands to be on stack. + * There is a special code in the register allocator that forces long arguments in registers on x86. However T_OBJECT + * can be spilled just fine, and in that case the xor emission will fail. + */ + +import java.util.concurrent.atomic.*; +class C1ObjectSpillInLogicOp { + static public void main(String[] args) { + AtomicReferenceArray x = new AtomicReferenceArray(128); + Integer y = new Integer(0); + for (int i = 0; i < 50000; i++) { + x.getAndSet(i % x.length(), y); + } + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/startup/StartupOutput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/startup/StartupOutput.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,44 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8026949 + * @summary Test ensures correct VM output during startup + * @library ../../testlibrary + * + */ +import com.oracle.java.testlibrary.*; + +public class StartupOutput { + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + OutputAnalyzer out; + + pb = ProcessTools.createJavaProcessBuilder("-Xint", "-XX:+DisplayVMOutputToStdout", "-version"); + out = new OutputAnalyzer(pb.start()); + out.shouldNotContain("no space to run compilers"); + + out.shouldHaveExitValue(0); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/uncommontrap/TestStackBangRbp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/uncommontrap/TestStackBangRbp.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,294 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8028308 + * @summary rbp not restored when stack overflow is thrown from deopt/uncommon trap blobs + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangRbp::m1 -XX:CompileCommand=exclude,TestStackBangRbp::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangRbp + * + */ +public class TestStackBangRbp { + + static class UnloadedClass1 { + } + + static class UnloadedClass2 { + } + + static Object m1(boolean deopt) { + long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, + l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, + l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36, + l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48, + l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, + l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72, + l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84, + l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96, + l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107, + l108, l109, l110, l111, l112, l113, l114, l115, l116, l117, + l118, l119, l120, l121, l122, l123, l124, l125, l126, l127, + l128, l129, l130, l131, l132, l133, l134, l135, l136, l137, + l138, l139, l140, l141, l142, l143, l144, l145, l146, l147, + l148, l149, l150, l151, l152, l153, l154, l155, l156, l157, + l158, l159, l160, l161, l162, l163, l164, l165, l166, l167, + l168, l169, l170, l171, l172, l173, l174, l175, l176, l177, + l178, l179, l180, l181, l182, l183, l184, l185, l186, l187, + l188, l189, l190, l191, l192, l193, l194, l195, l196, l197, + l198, l199, l200, l201, l202, l203, l204, l205, l206, l207, + l208, l209, l210, l211, l212, l213, l214, l215, l216, l217, + l218, l219, l220, l221, l222, l223, l224, l225, l226, l227, + l228, l229, l230, l231, l232, l233, l234, l235, l236, l237, + l238, l239, l240, l241, l242, l243, l244, l245, l246, l247, + l248, l249, l250, l251, l252, l253, l254, l255, l256, l257, + l258, l259, l260, l261, l262, l263, l264, l265, l266, l267, + l268, l269, l270, l271, l272, l273, l274, l275, l276, l277, + l278, l279, l280, l281, l282, l283, l284, l285, l286, l287, + l288, l289, l290, l291, l292, l293, l294, l295, l296, l297, + l298, l299, l300, l301, l302, l303, l304, l305, l306, l307, + l308, l309, l310, l311, l312, l313, l314, l315, l316, l317, + l318, l319, l320, l321, l322, l323, l324, l325, l326, l327, + l328, l329, l330, l331, l332, l333, l334, l335, l336, l337, + l338, l339, l340, l341, l342, l343, l344, l345, l346, l347, + l348, l349, l350, l351, l352, l353, l354, l355, l356, l357, + l358, l359, l360, l361, l362, l363, l364, l365, l366, l367, + l368, l369, l370, l371, l372, l373, l374, l375, l376, l377, + l378, l379, l380, l381, l382, l383, l384, l385, l386, l387, + l388, l389, l390, l391, l392, l393, l394, l395, l396, l397, + l398, l399, l400, l401, l402, l403, l404, l405, l406, l407, + l408, l409, l410, l411, l412, l413, l414, l415, l416, l417, + l418, l419, l420, l421, l422, l423, l424, l425, l426, l427, + l428, l429, l430, l431, l432, l433, l434, l435, l436, l437, + l438, l439, l440, l441, l442, l443, l444, l445, l446, l447, + l448, l449, l450, l451, l452, l453, l454, l455, l456, l457, + l458, l459, l460, l461, l462, l463, l464, l465, l466, l467, + l468, l469, l470, l471, l472, l473, l474, l475, l476, l477, + l478, l479, l480, l481, l482, l483, l484, l485, l486, l487, + l488, l489, l490, l491, l492, l493, l494, l495, l496, l497, + l498, l499, l500, l501, l502, l503, l504, l505, l506, l507, + l508, l509, l510, l511; + + long ll0, ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, ll9, ll10, ll11, ll12, + ll13, ll14, ll15, ll16, ll17, ll18, ll19, ll20, ll21, ll22, ll23, ll24, + ll25, ll26, ll27, ll28, ll29, ll30, ll31, ll32, ll33, ll34, ll35, ll36, + ll37, ll38, ll39, ll40, ll41, ll42, ll43, ll44, ll45, ll46, ll47, ll48, + ll49, ll50, ll51, ll52, ll53, ll54, ll55, ll56, ll57, ll58, ll59, ll60, + ll61, ll62, ll63, ll64, ll65, ll66, ll67, ll68, ll69, ll70, ll71, ll72, + ll73, ll74, ll75, ll76, ll77, ll78, ll79, ll80, ll81, ll82, ll83, ll84, + ll85, ll86, ll87, ll88, ll89, ll90, ll91, ll92, ll93, ll94, ll95, ll96, + ll97, ll98, ll99, ll100, ll101, ll102, ll103, ll104, ll105, ll106, ll107, + ll108, ll109, ll110, ll111, ll112, ll113, ll114, ll115, ll116, ll117, + ll118, ll119, ll120, ll121, ll122, ll123, ll124, ll125, ll126, ll127, + ll128, ll129, ll130, ll131, ll132, ll133, ll134, ll135, ll136, ll137, + ll138, ll139, ll140, ll141, ll142, ll143, ll144, ll145, ll146, ll147, + ll148, ll149, ll150, ll151, ll152, ll153, ll154, ll155, ll156, ll157, + ll158, ll159, ll160, ll161, ll162, ll163, ll164, ll165, ll166, ll167, + ll168, ll169, ll170, ll171, ll172, ll173, ll174, ll175, ll176, ll177, + ll178, ll179, ll180, ll181, ll182, ll183, ll184, ll185, ll186, ll187, + ll188, ll189, ll190, ll191, ll192, ll193, ll194, ll195, ll196, ll197, + ll198, ll199, ll200, ll201, ll202, ll203, ll204, ll205, ll206, ll207, + ll208, ll209, ll210, ll211, ll212, ll213, ll214, ll215, ll216, ll217, + ll218, ll219, ll220, ll221, ll222, ll223, ll224, ll225, ll226, ll227, + ll228, ll229, ll230, ll231, ll232, ll233, ll234, ll235, ll236, ll237, + ll238, ll239, ll240, ll241, ll242, ll243, ll244, ll245, ll246, ll247, + ll248, ll249, ll250, ll251, ll252, ll253, ll254, ll255, ll256, ll257, + ll258, ll259, ll260, ll261, ll262, ll263, ll264, ll265, ll266, ll267, + ll268, ll269, ll270, ll271, ll272, ll273, ll274, ll275, ll276, ll277, + ll278, ll279, ll280, ll281, ll282, ll283, ll284, ll285, ll286, ll287, + ll288, ll289, ll290, ll291, ll292, ll293, ll294, ll295, ll296, ll297, + ll298, ll299, ll300, ll301, ll302, ll303, ll304, ll305, ll306, ll307, + ll308, ll309, ll310, ll311, ll312, ll313, ll314, ll315, ll316, ll317, + ll318, ll319, ll320, ll321, ll322, ll323, ll324, ll325, ll326, ll327, + ll328, ll329, ll330, ll331, ll332, ll333, ll334, ll335, ll336, ll337, + ll338, ll339, ll340, ll341, ll342, ll343, ll344, ll345, ll346, ll347, + ll348, ll349, ll350, ll351, ll352, ll353, ll354, ll355, ll356, ll357, + ll358, ll359, ll360, ll361, ll362, ll363, ll364, ll365, ll366, ll367, + ll368, ll369, ll370, ll371, ll372, ll373, ll374, ll375, ll376, ll377, + ll378, ll379, ll380, ll381, ll382, ll383, ll384, ll385, ll386, ll387, + ll388, ll389, ll390, ll391, ll392, ll393, ll394, ll395, ll396, ll397, + ll398, ll399, ll400, ll401, ll402, ll403, ll404, ll405, ll406, ll407, + ll408, ll409, ll410, ll411, ll412, ll413, ll414, ll415, ll416, ll417, + ll418, ll419, ll420, ll421, ll422, ll423, ll424, ll425, ll426, ll427, + ll428, ll429, ll430, ll431, ll432, ll433, ll434, ll435, ll436, ll437, + ll438, ll439, ll440, ll441, ll442, ll443, ll444, ll445, ll446, ll447, + ll448, ll449, ll450, ll451, ll452, ll453, ll454, ll455, ll456, ll457, + ll458, ll459, ll460, ll461, ll462, ll463, ll464, ll465, ll466, ll467, + ll468, ll469, ll470, ll471, ll472, ll473, ll474, ll475, ll476, ll477, + ll478, ll479, ll480, ll481, ll482, ll483, ll484, ll485, ll486, ll487, + ll488, ll489, ll490, ll491, ll492, ll493, ll494, ll495, ll496, ll497, + ll498, ll499, ll500, ll501, ll502, ll503, ll504, ll505, ll506, ll507, + ll508, ll509, ll510, ll511; + + int i1 = TestStackBangRbp.i1; + int i2 = TestStackBangRbp.i2; + int i3 = TestStackBangRbp.i3; + int i4 = TestStackBangRbp.i4; + int i5 = TestStackBangRbp.i5; + int i6 = TestStackBangRbp.i6; + int i7 = TestStackBangRbp.i7; + int i8 = TestStackBangRbp.i8; + int i9 = TestStackBangRbp.i9; + int i10 = TestStackBangRbp.i10; + int i11 = TestStackBangRbp.i11; + int i12 = TestStackBangRbp.i12; + int i13 = TestStackBangRbp.i13; + int i14 = TestStackBangRbp.i14; + int i15 = TestStackBangRbp.i15; + int i16 = TestStackBangRbp.i16; + + TestStackBangRbp.i1 = i1; + TestStackBangRbp.i2 = i2; + TestStackBangRbp.i3 = i3; + TestStackBangRbp.i4 = i4; + TestStackBangRbp.i5 = i5; + TestStackBangRbp.i6 = i6; + TestStackBangRbp.i7 = i7; + TestStackBangRbp.i8 = i8; + TestStackBangRbp.i9 = i9; + TestStackBangRbp.i10 = i10; + TestStackBangRbp.i11 = i11; + TestStackBangRbp.i12 = i12; + TestStackBangRbp.i13 = i13; + TestStackBangRbp.i14 = i14; + TestStackBangRbp.i15 = i15; + TestStackBangRbp.i16 = i16; + + if (deopt) { + // deoptimize with integer in rbp + UnloadedClass1 res = new UnloadedClass1(); // forces deopt with c2 + return res; + } + return null; + } + + static boolean m2(boolean deopt) { + // call m2 recursively until stack overflow. Then call m3 that + // will call m1 and trigger and deopt in m1 while keeping a + // lot of objects live in registers at the call to m1 + + long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, + l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, + l25, l26, l27, l28, l29, l30, l31, l32, l33, l34, l35, l36, + l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47, l48, + l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, + l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, l71, l72, + l73, l74, l75, l76, l77, l78, l79, l80, l81, l82, l83, l84, + l85, l86, l87, l88, l89, l90, l91, l92, l93, l94, l95, l96, + l97, l98, l99, l100, l101, l102, l103, l104, l105, l106, l107, + l108, l109, l110, l111, l112, l113, l114, l115, l116, l117, + l118, l119, l120, l121, l122, l123, l124, l125, l126, l127, + l128, l129, l130, l131, l132, l133, l134, l135, l136, l137, + l138, l139, l140, l141, l142, l143, l144, l145, l146, l147, + l148, l149, l150, l151, l152, l153, l154, l155, l156, l157, + l158, l159, l160, l161, l162, l163, l164, l165, l166, l167, + l168, l169, l170, l171, l172, l173, l174, l175, l176, l177, + l178, l179, l180, l181, l182, l183, l184, l185, l186, l187, + l188, l189, l190, l191, l192, l193, l194, l195, l196, l197, + l198, l199, l200, l201, l202, l203, l204, l205, l206, l207, + l208, l209, l210, l211, l212, l213, l214, l215, l216, l217, + l218, l219, l220, l221, l222, l223, l224, l225, l226, l227, + l228, l229, l230, l231, l232, l233, l234, l235, l236, l237, + l238, l239, l240, l241, l242, l243, l244, l245, l246, l247, + l248, l249, l250, l251, l252, l253, l254, l255, l256, l257, + l258, l259, l260, l261, l262, l263, l264, l265, l266, l267, + l268, l269, l270, l271, l272, l273, l274, l275, l276, l277, + l278, l279, l280, l281, l282, l283, l284, l285, l286, l287, + l288, l289, l290, l291, l292, l293, l294, l295, l296, l297, + l298, l299, l300, l301, l302, l303, l304, l305, l306, l307, + l308, l309, l310, l311, l312, l313, l314, l315, l316, l317, + l318, l319, l320, l321, l322, l323, l324, l325, l326, l327, + l328, l329, l330, l331, l332, l333, l334, l335, l336, l337, + l338, l339, l340, l341, l342, l343, l344, l345, l346, l347, + l348, l349, l350, l351, l352, l353, l354, l355, l356, l357, + l358, l359, l360, l361, l362, l363, l364, l365, l366, l367, + l368, l369, l370, l371, l372, l373, l374, l375, l376, l377, + l378, l379, l380, l381, l382, l383, l384, l385, l386, l387, + l388, l389, l390, l391, l392, l393, l394, l395, l396, l397, + l398, l399, l400, l401, l402, l403, l404, l405, l406, l407, + l408, l409, l410, l411, l412, l413, l414, l415, l416, l417, + l418, l419, l420, l421, l422, l423, l424, l425, l426, l427, + l428, l429, l430, l431, l432, l433, l434, l435, l436, l437, + l438, l439, l440, l441, l442, l443, l444, l445, l446, l447, + l448, l449, l450, l451, l452, l453, l454, l455, l456, l457, + l458, l459, l460, l461, l462, l463, l464, l465, l466, l467, + l468, l469, l470, l471, l472, l473, l474, l475, l476, l477, + l478, l479, l480, l481, l482, l483, l484, l485, l486, l487, + l488, l489, l490, l491, l492, l493, l494, l495, l496, l497, + l498, l499, l500, l501, l502, l503, l504, l505, l506, l507, + l508, l509, l510, l511; + + boolean do_m3 = false; + try { + do_m3 = m2(deopt); + } catch (StackOverflowError e) { + return true; + } + if (do_m3) { + m3(deopt); + } + return false; + } + + static volatile Object o1 = new Object(); + + static volatile int i1 = 1; + static volatile int i2 = 2; + static volatile int i3 = 3; + static volatile int i4 = 4; + static volatile int i5 = 5; + static volatile int i6 = 6; + static volatile int i7 = 7; + static volatile int i8 = 8; + static volatile int i9 = 9; + static volatile int i10 = 10; + static volatile int i11 = 11; + static volatile int i12 = 12; + static volatile int i13 = 13; + static volatile int i14 = 14; + static volatile int i15 = 15; + static volatile int i16 = 16; + + static void m3(boolean deopt) { + Object o1 = TestStackBangRbp.o1; + TestStackBangRbp.o1 = o1; + + try { + m1(deopt); + } catch (StackOverflowError e) { + // deoptimize again. rbp holds an integer. It should have an object. + UnloadedClass2 res = new UnloadedClass2(); // forces deopt with c2 + } + TestStackBangRbp.o1 = o1; + } + + static public void main(String[] args) { + // get m1 & m3 compiled + for (int i = 0; i < 20000; i++) { + m1(false); + m3(false); + } + m2(true); + + System.out.println("TEST PASSED"); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/compiler/uncommontrap/UncommonTrapStackBang.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/uncommontrap/UncommonTrapStackBang.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,10908 @@ +/* + * 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. + * + */ + +/** + * @test + * @bug 8026775 + * @summary Uncommon trap blob did not bang all the stack shadow pages + * + * @run main/othervm -server -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation UncommonTrapStackBang + * @run main/othervm -server -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation UncommonTrapStackBang + * + * + * Note: This test does not reproduce the problem with absolute + * certainty. Empirically the bug reproduces on Windows some 80+% of + * the time. Setting everything up to fail in 100% of the cases turns + * out to be tricky at best. + * + * + * The goal of this test is to set up the following stack: + * + * doIt() + * eatStack() + * ... + * eatStack() + * run() + * + * + * When doIt() gets executed it will hit an uncommon trap and expand + * into a huge interpreter frame. The doIt method then calls the + * compiled version of StringBuilder.() which does a single + * stack bang StackShadowPages down. + * + * The uncommon trap blob is supposed to prepare for the interpreter + * by pre-touching stack pages. The bug was that it didn't correctly + * pre-touch all the stack shadow pages, leaving a "hole" on the stack + * which raises an exception on Windows when the stack bang in + * StringBuilder is performed. + */ +public class UncommonTrapStackBang extends Thread { + class Foo { } + + public static void main(String[] args) throws Exception { + doWarmup(); + + // Fork off a new thread to increase odds of the stack being unmapped + UncommonTrapStackBang htsb = new UncommonTrapStackBang(); + htsb.run(); + htsb.join(); + } + + // Make sure: + // + // a) StringBuilder.()V is compiled + // b) doIt() is compiled with an uncommon trap in the unlikely path + public static void doWarmup() { + for (int i = 0; i < 100_000; i++) { + new StringBuilder(); + + doIt(false); + } + } + + public void run() { + eatStack(200); + } + + // Consume some stack to get down to some unused/unmapped pages, + // then call doIt and provoke the uncommon trap/deoptimization + private void eatStack(int n) { + if (n <= 0) { + doIt(true); + return; + } + + eatStack(n - 1); + } + + static public void doIt(boolean unlikely) { + int i0; + int i1; + int i2; + int i3; + int i4; + int i5; + int i6; + int i7; + int i8; + int i9; + int i10; + int i11; + int i12; + int i13; + int i14; + int i15; + int i16; + int i17; + int i18; + int i19; + int i20; + int i21; + int i22; + int i23; + int i24; + int i25; + int i26; + int i27; + int i28; + int i29; + int i30; + int i31; + int i32; + int i33; + int i34; + int i35; + int i36; + int i37; + int i38; + int i39; + int i40; + int i41; + int i42; + int i43; + int i44; + int i45; + int i46; + int i47; + int i48; + int i49; + int i50; + int i51; + int i52; + int i53; + int i54; + int i55; + int i56; + int i57; + int i58; + int i59; + int i60; + int i61; + int i62; + int i63; + int i64; + int i65; + int i66; + int i67; + int i68; + int i69; + int i70; + int i71; + int i72; + int i73; + int i74; + int i75; + int i76; + int i77; + int i78; + int i79; + int i80; + int i81; + int i82; + int i83; + int i84; + int i85; + int i86; + int i87; + int i88; + int i89; + int i90; + int i91; + int i92; + int i93; + int i94; + int i95; + int i96; + int i97; + int i98; + int i99; + int i100; + int i101; + int i102; + int i103; + int i104; + int i105; + int i106; + int i107; + int i108; + int i109; + int i110; + int i111; + int i112; + int i113; + int i114; + int i115; + int i116; + int i117; + int i118; + int i119; + int i120; + int i121; + int i122; + int i123; + int i124; + int i125; + int i126; + int i127; + int i128; + int i129; + int i130; + int i131; + int i132; + int i133; + int i134; + int i135; + int i136; + int i137; + int i138; + int i139; + int i140; + int i141; + int i142; + int i143; + int i144; + int i145; + int i146; + int i147; + int i148; + int i149; + int i150; + int i151; + int i152; + int i153; + int i154; + int i155; + int i156; + int i157; + int i158; + int i159; + int i160; + int i161; + int i162; + int i163; + int i164; + int i165; + int i166; + int i167; + int i168; + int i169; + int i170; + int i171; + int i172; + int i173; + int i174; + int i175; + int i176; + int i177; + int i178; + int i179; + int i180; + int i181; + int i182; + int i183; + int i184; + int i185; + int i186; + int i187; + int i188; + int i189; + int i190; + int i191; + int i192; + int i193; + int i194; + int i195; + int i196; + int i197; + int i198; + int i199; + int i200; + int i201; + int i202; + int i203; + int i204; + int i205; + int i206; + int i207; + int i208; + int i209; + int i210; + int i211; + int i212; + int i213; + int i214; + int i215; + int i216; + int i217; + int i218; + int i219; + int i220; + int i221; + int i222; + int i223; + int i224; + int i225; + int i226; + int i227; + int i228; + int i229; + int i230; + int i231; + int i232; + int i233; + int i234; + int i235; + int i236; + int i237; + int i238; + int i239; + int i240; + int i241; + int i242; + int i243; + int i244; + int i245; + int i246; + int i247; + int i248; + int i249; + int i250; + int i251; + int i252; + int i253; + int i254; + int i255; + int i256; + int i257; + int i258; + int i259; + int i260; + int i261; + int i262; + int i263; + int i264; + int i265; + int i266; + int i267; + int i268; + int i269; + int i270; + int i271; + int i272; + int i273; + int i274; + int i275; + int i276; + int i277; + int i278; + int i279; + int i280; + int i281; + int i282; + int i283; + int i284; + int i285; + int i286; + int i287; + int i288; + int i289; + int i290; + int i291; + int i292; + int i293; + int i294; + int i295; + int i296; + int i297; + int i298; + int i299; + int i300; + int i301; + int i302; + int i303; + int i304; + int i305; + int i306; + int i307; + int i308; + int i309; + int i310; + int i311; + int i312; + int i313; + int i314; + int i315; + int i316; + int i317; + int i318; + int i319; + int i320; + int i321; + int i322; + int i323; + int i324; + int i325; + int i326; + int i327; + int i328; + int i329; + int i330; + int i331; + int i332; + int i333; + int i334; + int i335; + int i336; + int i337; + int i338; + int i339; + int i340; + int i341; + int i342; + int i343; + int i344; + int i345; + int i346; + int i347; + int i348; + int i349; + int i350; + int i351; + int i352; + int i353; + int i354; + int i355; + int i356; + int i357; + int i358; + int i359; + int i360; + int i361; + int i362; + int i363; + int i364; + int i365; + int i366; + int i367; + int i368; + int i369; + int i370; + int i371; + int i372; + int i373; + int i374; + int i375; + int i376; + int i377; + int i378; + int i379; + int i380; + int i381; + int i382; + int i383; + int i384; + int i385; + int i386; + int i387; + int i388; + int i389; + int i390; + int i391; + int i392; + int i393; + int i394; + int i395; + int i396; + int i397; + int i398; + int i399; + int i400; + int i401; + int i402; + int i403; + int i404; + int i405; + int i406; + int i407; + int i408; + int i409; + int i410; + int i411; + int i412; + int i413; + int i414; + int i415; + int i416; + int i417; + int i418; + int i419; + int i420; + int i421; + int i422; + int i423; + int i424; + int i425; + int i426; + int i427; + int i428; + int i429; + int i430; + int i431; + int i432; + int i433; + int i434; + int i435; + int i436; + int i437; + int i438; + int i439; + int i440; + int i441; + int i442; + int i443; + int i444; + int i445; + int i446; + int i447; + int i448; + int i449; + int i450; + int i451; + int i452; + int i453; + int i454; + int i455; + int i456; + int i457; + int i458; + int i459; + int i460; + int i461; + int i462; + int i463; + int i464; + int i465; + int i466; + int i467; + int i468; + int i469; + int i470; + int i471; + int i472; + int i473; + int i474; + int i475; + int i476; + int i477; + int i478; + int i479; + int i480; + int i481; + int i482; + int i483; + int i484; + int i485; + int i486; + int i487; + int i488; + int i489; + int i490; + int i491; + int i492; + int i493; + int i494; + int i495; + int i496; + int i497; + int i498; + int i499; + int i500; + int i501; + int i502; + int i503; + int i504; + int i505; + int i506; + int i507; + int i508; + int i509; + int i510; + int i511; + int i512; + int i513; + int i514; + int i515; + int i516; + int i517; + int i518; + int i519; + int i520; + int i521; + int i522; + int i523; + int i524; + int i525; + int i526; + int i527; + int i528; + int i529; + int i530; + int i531; + int i532; + int i533; + int i534; + int i535; + int i536; + int i537; + int i538; + int i539; + int i540; + int i541; + int i542; + int i543; + int i544; + int i545; + int i546; + int i547; + int i548; + int i549; + int i550; + int i551; + int i552; + int i553; + int i554; + int i555; + int i556; + int i557; + int i558; + int i559; + int i560; + int i561; + int i562; + int i563; + int i564; + int i565; + int i566; + int i567; + int i568; + int i569; + int i570; + int i571; + int i572; + int i573; + int i574; + int i575; + int i576; + int i577; + int i578; + int i579; + int i580; + int i581; + int i582; + int i583; + int i584; + int i585; + int i586; + int i587; + int i588; + int i589; + int i590; + int i591; + int i592; + int i593; + int i594; + int i595; + int i596; + int i597; + int i598; + int i599; + int i600; + int i601; + int i602; + int i603; + int i604; + int i605; + int i606; + int i607; + int i608; + int i609; + int i610; + int i611; + int i612; + int i613; + int i614; + int i615; + int i616; + int i617; + int i618; + int i619; + int i620; + int i621; + int i622; + int i623; + int i624; + int i625; + int i626; + int i627; + int i628; + int i629; + int i630; + int i631; + int i632; + int i633; + int i634; + int i635; + int i636; + int i637; + int i638; + int i639; + int i640; + int i641; + int i642; + int i643; + int i644; + int i645; + int i646; + int i647; + int i648; + int i649; + int i650; + int i651; + int i652; + int i653; + int i654; + int i655; + int i656; + int i657; + int i658; + int i659; + int i660; + int i661; + int i662; + int i663; + int i664; + int i665; + int i666; + int i667; + int i668; + int i669; + int i670; + int i671; + int i672; + int i673; + int i674; + int i675; + int i676; + int i677; + int i678; + int i679; + int i680; + int i681; + int i682; + int i683; + int i684; + int i685; + int i686; + int i687; + int i688; + int i689; + int i690; + int i691; + int i692; + int i693; + int i694; + int i695; + int i696; + int i697; + int i698; + int i699; + int i700; + int i701; + int i702; + int i703; + int i704; + int i705; + int i706; + int i707; + int i708; + int i709; + int i710; + int i711; + int i712; + int i713; + int i714; + int i715; + int i716; + int i717; + int i718; + int i719; + int i720; + int i721; + int i722; + int i723; + int i724; + int i725; + int i726; + int i727; + int i728; + int i729; + int i730; + int i731; + int i732; + int i733; + int i734; + int i735; + int i736; + int i737; + int i738; + int i739; + int i740; + int i741; + int i742; + int i743; + int i744; + int i745; + int i746; + int i747; + int i748; + int i749; + int i750; + int i751; + int i752; + int i753; + int i754; + int i755; + int i756; + int i757; + int i758; + int i759; + int i760; + int i761; + int i762; + int i763; + int i764; + int i765; + int i766; + int i767; + int i768; + int i769; + int i770; + int i771; + int i772; + int i773; + int i774; + int i775; + int i776; + int i777; + int i778; + int i779; + int i780; + int i781; + int i782; + int i783; + int i784; + int i785; + int i786; + int i787; + int i788; + int i789; + int i790; + int i791; + int i792; + int i793; + int i794; + int i795; + int i796; + int i797; + int i798; + int i799; + int i800; + int i801; + int i802; + int i803; + int i804; + int i805; + int i806; + int i807; + int i808; + int i809; + int i810; + int i811; + int i812; + int i813; + int i814; + int i815; + int i816; + int i817; + int i818; + int i819; + int i820; + int i821; + int i822; + int i823; + int i824; + int i825; + int i826; + int i827; + int i828; + int i829; + int i830; + int i831; + int i832; + int i833; + int i834; + int i835; + int i836; + int i837; + int i838; + int i839; + int i840; + int i841; + int i842; + int i843; + int i844; + int i845; + int i846; + int i847; + int i848; + int i849; + int i850; + int i851; + int i852; + int i853; + int i854; + int i855; + int i856; + int i857; + int i858; + int i859; + int i860; + int i861; + int i862; + int i863; + int i864; + int i865; + int i866; + int i867; + int i868; + int i869; + int i870; + int i871; + int i872; + int i873; + int i874; + int i875; + int i876; + int i877; + int i878; + int i879; + int i880; + int i881; + int i882; + int i883; + int i884; + int i885; + int i886; + int i887; + int i888; + int i889; + int i890; + int i891; + int i892; + int i893; + int i894; + int i895; + int i896; + int i897; + int i898; + int i899; + int i900; + int i901; + int i902; + int i903; + int i904; + int i905; + int i906; + int i907; + int i908; + int i909; + int i910; + int i911; + int i912; + int i913; + int i914; + int i915; + int i916; + int i917; + int i918; + int i919; + int i920; + int i921; + int i922; + int i923; + int i924; + int i925; + int i926; + int i927; + int i928; + int i929; + int i930; + int i931; + int i932; + int i933; + int i934; + int i935; + int i936; + int i937; + int i938; + int i939; + int i940; + int i941; + int i942; + int i943; + int i944; + int i945; + int i946; + int i947; + int i948; + int i949; + int i950; + int i951; + int i952; + int i953; + int i954; + int i955; + int i956; + int i957; + int i958; + int i959; + int i960; + int i961; + int i962; + int i963; + int i964; + int i965; + int i966; + int i967; + int i968; + int i969; + int i970; + int i971; + int i972; + int i973; + int i974; + int i975; + int i976; + int i977; + int i978; + int i979; + int i980; + int i981; + int i982; + int i983; + int i984; + int i985; + int i986; + int i987; + int i988; + int i989; + int i990; + int i991; + int i992; + int i993; + int i994; + int i995; + int i996; + int i997; + int i998; + int i999; + int i1000; + int i1001; + int i1002; + int i1003; + int i1004; + int i1005; + int i1006; + int i1007; + int i1008; + int i1009; + int i1010; + int i1011; + int i1012; + int i1013; + int i1014; + int i1015; + int i1016; + int i1017; + int i1018; + int i1019; + int i1020; + int i1021; + int i1022; + int i1023; + int i1024; + int i1025; + int i1026; + int i1027; + int i1028; + int i1029; + int i1030; + int i1031; + int i1032; + int i1033; + int i1034; + int i1035; + int i1036; + int i1037; + int i1038; + int i1039; + int i1040; + int i1041; + int i1042; + int i1043; + int i1044; + int i1045; + int i1046; + int i1047; + int i1048; + int i1049; + int i1050; + int i1051; + int i1052; + int i1053; + int i1054; + int i1055; + int i1056; + int i1057; + int i1058; + int i1059; + int i1060; + int i1061; + int i1062; + int i1063; + int i1064; + int i1065; + int i1066; + int i1067; + int i1068; + int i1069; + int i1070; + int i1071; + int i1072; + int i1073; + int i1074; + int i1075; + int i1076; + int i1077; + int i1078; + int i1079; + int i1080; + int i1081; + int i1082; + int i1083; + int i1084; + int i1085; + int i1086; + int i1087; + int i1088; + int i1089; + int i1090; + int i1091; + int i1092; + int i1093; + int i1094; + int i1095; + int i1096; + int i1097; + int i1098; + int i1099; + int i1100; + int i1101; + int i1102; + int i1103; + int i1104; + int i1105; + int i1106; + int i1107; + int i1108; + int i1109; + int i1110; + int i1111; + int i1112; + int i1113; + int i1114; + int i1115; + int i1116; + int i1117; + int i1118; + int i1119; + int i1120; + int i1121; + int i1122; + int i1123; + int i1124; + int i1125; + int i1126; + int i1127; + int i1128; + int i1129; + int i1130; + int i1131; + int i1132; + int i1133; + int i1134; + int i1135; + int i1136; + int i1137; + int i1138; + int i1139; + int i1140; + int i1141; + int i1142; + int i1143; + int i1144; + int i1145; + int i1146; + int i1147; + int i1148; + int i1149; + int i1150; + int i1151; + int i1152; + int i1153; + int i1154; + int i1155; + int i1156; + int i1157; + int i1158; + int i1159; + int i1160; + int i1161; + int i1162; + int i1163; + int i1164; + int i1165; + int i1166; + int i1167; + int i1168; + int i1169; + int i1170; + int i1171; + int i1172; + int i1173; + int i1174; + int i1175; + int i1176; + int i1177; + int i1178; + int i1179; + int i1180; + int i1181; + int i1182; + int i1183; + int i1184; + int i1185; + int i1186; + int i1187; + int i1188; + int i1189; + int i1190; + int i1191; + int i1192; + int i1193; + int i1194; + int i1195; + int i1196; + int i1197; + int i1198; + int i1199; + int i1200; + int i1201; + int i1202; + int i1203; + int i1204; + int i1205; + int i1206; + int i1207; + int i1208; + int i1209; + int i1210; + int i1211; + int i1212; + int i1213; + int i1214; + int i1215; + int i1216; + int i1217; + int i1218; + int i1219; + int i1220; + int i1221; + int i1222; + int i1223; + int i1224; + int i1225; + int i1226; + int i1227; + int i1228; + int i1229; + int i1230; + int i1231; + int i1232; + int i1233; + int i1234; + int i1235; + int i1236; + int i1237; + int i1238; + int i1239; + int i1240; + int i1241; + int i1242; + int i1243; + int i1244; + int i1245; + int i1246; + int i1247; + int i1248; + int i1249; + int i1250; + int i1251; + int i1252; + int i1253; + int i1254; + int i1255; + int i1256; + int i1257; + int i1258; + int i1259; + int i1260; + int i1261; + int i1262; + int i1263; + int i1264; + int i1265; + int i1266; + int i1267; + int i1268; + int i1269; + int i1270; + int i1271; + int i1272; + int i1273; + int i1274; + int i1275; + int i1276; + int i1277; + int i1278; + int i1279; + int i1280; + int i1281; + int i1282; + int i1283; + int i1284; + int i1285; + int i1286; + int i1287; + int i1288; + int i1289; + int i1290; + int i1291; + int i1292; + int i1293; + int i1294; + int i1295; + int i1296; + int i1297; + int i1298; + int i1299; + int i1300; + int i1301; + int i1302; + int i1303; + int i1304; + int i1305; + int i1306; + int i1307; + int i1308; + int i1309; + int i1310; + int i1311; + int i1312; + int i1313; + int i1314; + int i1315; + int i1316; + int i1317; + int i1318; + int i1319; + int i1320; + int i1321; + int i1322; + int i1323; + int i1324; + int i1325; + int i1326; + int i1327; + int i1328; + int i1329; + int i1330; + int i1331; + int i1332; + int i1333; + int i1334; + int i1335; + int i1336; + int i1337; + int i1338; + int i1339; + int i1340; + int i1341; + int i1342; + int i1343; + int i1344; + int i1345; + int i1346; + int i1347; + int i1348; + int i1349; + int i1350; + int i1351; + int i1352; + int i1353; + int i1354; + int i1355; + int i1356; + int i1357; + int i1358; + int i1359; + int i1360; + int i1361; + int i1362; + int i1363; + int i1364; + int i1365; + int i1366; + int i1367; + int i1368; + int i1369; + int i1370; + int i1371; + int i1372; + int i1373; + int i1374; + int i1375; + int i1376; + int i1377; + int i1378; + int i1379; + int i1380; + int i1381; + int i1382; + int i1383; + int i1384; + int i1385; + int i1386; + int i1387; + int i1388; + int i1389; + int i1390; + int i1391; + int i1392; + int i1393; + int i1394; + int i1395; + int i1396; + int i1397; + int i1398; + int i1399; + int i1400; + int i1401; + int i1402; + int i1403; + int i1404; + int i1405; + int i1406; + int i1407; + int i1408; + int i1409; + int i1410; + int i1411; + int i1412; + int i1413; + int i1414; + int i1415; + int i1416; + int i1417; + int i1418; + int i1419; + int i1420; + int i1421; + int i1422; + int i1423; + int i1424; + int i1425; + int i1426; + int i1427; + int i1428; + int i1429; + int i1430; + int i1431; + int i1432; + int i1433; + int i1434; + int i1435; + int i1436; + int i1437; + int i1438; + int i1439; + int i1440; + int i1441; + int i1442; + int i1443; + int i1444; + int i1445; + int i1446; + int i1447; + int i1448; + int i1449; + int i1450; + int i1451; + int i1452; + int i1453; + int i1454; + int i1455; + int i1456; + int i1457; + int i1458; + int i1459; + int i1460; + int i1461; + int i1462; + int i1463; + int i1464; + int i1465; + int i1466; + int i1467; + int i1468; + int i1469; + int i1470; + int i1471; + int i1472; + int i1473; + int i1474; + int i1475; + int i1476; + int i1477; + int i1478; + int i1479; + int i1480; + int i1481; + int i1482; + int i1483; + int i1484; + int i1485; + int i1486; + int i1487; + int i1488; + int i1489; + int i1490; + int i1491; + int i1492; + int i1493; + int i1494; + int i1495; + int i1496; + int i1497; + int i1498; + int i1499; + int i1500; + int i1501; + int i1502; + int i1503; + int i1504; + int i1505; + int i1506; + int i1507; + int i1508; + int i1509; + int i1510; + int i1511; + int i1512; + int i1513; + int i1514; + int i1515; + int i1516; + int i1517; + int i1518; + int i1519; + int i1520; + int i1521; + int i1522; + int i1523; + int i1524; + int i1525; + int i1526; + int i1527; + int i1528; + int i1529; + int i1530; + int i1531; + int i1532; + int i1533; + int i1534; + int i1535; + int i1536; + int i1537; + int i1538; + int i1539; + int i1540; + int i1541; + int i1542; + int i1543; + int i1544; + int i1545; + int i1546; + int i1547; + int i1548; + int i1549; + int i1550; + int i1551; + int i1552; + int i1553; + int i1554; + int i1555; + int i1556; + int i1557; + int i1558; + int i1559; + int i1560; + int i1561; + int i1562; + int i1563; + int i1564; + int i1565; + int i1566; + int i1567; + int i1568; + int i1569; + int i1570; + int i1571; + int i1572; + int i1573; + int i1574; + int i1575; + int i1576; + int i1577; + int i1578; + int i1579; + int i1580; + int i1581; + int i1582; + int i1583; + int i1584; + int i1585; + int i1586; + int i1587; + int i1588; + int i1589; + int i1590; + int i1591; + int i1592; + int i1593; + int i1594; + int i1595; + int i1596; + int i1597; + int i1598; + int i1599; + int i1600; + int i1601; + int i1602; + int i1603; + int i1604; + int i1605; + int i1606; + int i1607; + int i1608; + int i1609; + int i1610; + int i1611; + int i1612; + int i1613; + int i1614; + int i1615; + int i1616; + int i1617; + int i1618; + int i1619; + int i1620; + int i1621; + int i1622; + int i1623; + int i1624; + int i1625; + int i1626; + int i1627; + int i1628; + int i1629; + int i1630; + int i1631; + int i1632; + int i1633; + int i1634; + int i1635; + int i1636; + int i1637; + int i1638; + int i1639; + int i1640; + int i1641; + int i1642; + int i1643; + int i1644; + int i1645; + int i1646; + int i1647; + int i1648; + int i1649; + int i1650; + int i1651; + int i1652; + int i1653; + int i1654; + int i1655; + int i1656; + int i1657; + int i1658; + int i1659; + int i1660; + int i1661; + int i1662; + int i1663; + int i1664; + int i1665; + int i1666; + int i1667; + int i1668; + int i1669; + int i1670; + int i1671; + int i1672; + int i1673; + int i1674; + int i1675; + int i1676; + int i1677; + int i1678; + int i1679; + int i1680; + int i1681; + int i1682; + int i1683; + int i1684; + int i1685; + int i1686; + int i1687; + int i1688; + int i1689; + int i1690; + int i1691; + int i1692; + int i1693; + int i1694; + int i1695; + int i1696; + int i1697; + int i1698; + int i1699; + int i1700; + int i1701; + int i1702; + int i1703; + int i1704; + int i1705; + int i1706; + int i1707; + int i1708; + int i1709; + int i1710; + int i1711; + int i1712; + int i1713; + int i1714; + int i1715; + int i1716; + int i1717; + int i1718; + int i1719; + int i1720; + int i1721; + int i1722; + int i1723; + int i1724; + int i1725; + int i1726; + int i1727; + int i1728; + int i1729; + int i1730; + int i1731; + int i1732; + int i1733; + int i1734; + int i1735; + int i1736; + int i1737; + int i1738; + int i1739; + int i1740; + int i1741; + int i1742; + int i1743; + int i1744; + int i1745; + int i1746; + int i1747; + int i1748; + int i1749; + int i1750; + int i1751; + int i1752; + int i1753; + int i1754; + int i1755; + int i1756; + int i1757; + int i1758; + int i1759; + int i1760; + int i1761; + int i1762; + int i1763; + int i1764; + int i1765; + int i1766; + int i1767; + int i1768; + int i1769; + int i1770; + int i1771; + int i1772; + int i1773; + int i1774; + int i1775; + int i1776; + int i1777; + int i1778; + int i1779; + int i1780; + int i1781; + int i1782; + int i1783; + int i1784; + int i1785; + int i1786; + int i1787; + int i1788; + int i1789; + int i1790; + int i1791; + int i1792; + int i1793; + int i1794; + int i1795; + int i1796; + int i1797; + int i1798; + int i1799; + int i1800; + int i1801; + int i1802; + int i1803; + int i1804; + int i1805; + int i1806; + int i1807; + int i1808; + int i1809; + int i1810; + int i1811; + int i1812; + int i1813; + int i1814; + int i1815; + int i1816; + int i1817; + int i1818; + int i1819; + int i1820; + int i1821; + int i1822; + int i1823; + int i1824; + int i1825; + int i1826; + int i1827; + int i1828; + int i1829; + int i1830; + int i1831; + int i1832; + int i1833; + int i1834; + int i1835; + int i1836; + int i1837; + int i1838; + int i1839; + int i1840; + int i1841; + int i1842; + int i1843; + int i1844; + int i1845; + int i1846; + int i1847; + int i1848; + int i1849; + int i1850; + int i1851; + int i1852; + int i1853; + int i1854; + int i1855; + int i1856; + int i1857; + int i1858; + int i1859; + int i1860; + int i1861; + int i1862; + int i1863; + int i1864; + int i1865; + int i1866; + int i1867; + int i1868; + int i1869; + int i1870; + int i1871; + int i1872; + int i1873; + int i1874; + int i1875; + int i1876; + int i1877; + int i1878; + int i1879; + int i1880; + int i1881; + int i1882; + int i1883; + int i1884; + int i1885; + int i1886; + int i1887; + int i1888; + int i1889; + int i1890; + int i1891; + int i1892; + int i1893; + int i1894; + int i1895; + int i1896; + int i1897; + int i1898; + int i1899; + int i1900; + int i1901; + int i1902; + int i1903; + int i1904; + int i1905; + int i1906; + int i1907; + int i1908; + int i1909; + int i1910; + int i1911; + int i1912; + int i1913; + int i1914; + int i1915; + int i1916; + int i1917; + int i1918; + int i1919; + int i1920; + int i1921; + int i1922; + int i1923; + int i1924; + int i1925; + int i1926; + int i1927; + int i1928; + int i1929; + int i1930; + int i1931; + int i1932; + int i1933; + int i1934; + int i1935; + int i1936; + int i1937; + int i1938; + int i1939; + int i1940; + int i1941; + int i1942; + int i1943; + int i1944; + int i1945; + int i1946; + int i1947; + int i1948; + int i1949; + int i1950; + int i1951; + int i1952; + int i1953; + int i1954; + int i1955; + int i1956; + int i1957; + int i1958; + int i1959; + int i1960; + int i1961; + int i1962; + int i1963; + int i1964; + int i1965; + int i1966; + int i1967; + int i1968; + int i1969; + int i1970; + int i1971; + int i1972; + int i1973; + int i1974; + int i1975; + int i1976; + int i1977; + int i1978; + int i1979; + int i1980; + int i1981; + int i1982; + int i1983; + int i1984; + int i1985; + int i1986; + int i1987; + int i1988; + int i1989; + int i1990; + int i1991; + int i1992; + int i1993; + int i1994; + int i1995; + int i1996; + int i1997; + int i1998; + int i1999; + int i2000; + int i2001; + int i2002; + int i2003; + int i2004; + int i2005; + int i2006; + int i2007; + int i2008; + int i2009; + int i2010; + int i2011; + int i2012; + int i2013; + int i2014; + int i2015; + int i2016; + int i2017; + int i2018; + int i2019; + int i2020; + int i2021; + int i2022; + int i2023; + int i2024; + int i2025; + int i2026; + int i2027; + int i2028; + int i2029; + int i2030; + int i2031; + int i2032; + int i2033; + int i2034; + int i2035; + int i2036; + int i2037; + int i2038; + int i2039; + int i2040; + int i2041; + int i2042; + int i2043; + int i2044; + int i2045; + int i2046; + int i2047; + int i2048; + int i2049; + int i2050; + int i2051; + int i2052; + int i2053; + int i2054; + int i2055; + int i2056; + int i2057; + int i2058; + int i2059; + int i2060; + int i2061; + int i2062; + int i2063; + int i2064; + int i2065; + int i2066; + int i2067; + int i2068; + int i2069; + int i2070; + int i2071; + int i2072; + int i2073; + int i2074; + int i2075; + int i2076; + int i2077; + int i2078; + int i2079; + int i2080; + int i2081; + int i2082; + int i2083; + int i2084; + int i2085; + int i2086; + int i2087; + int i2088; + int i2089; + int i2090; + int i2091; + int i2092; + int i2093; + int i2094; + int i2095; + int i2096; + int i2097; + int i2098; + int i2099; + int i2100; + int i2101; + int i2102; + int i2103; + int i2104; + int i2105; + int i2106; + int i2107; + int i2108; + int i2109; + int i2110; + int i2111; + int i2112; + int i2113; + int i2114; + int i2115; + int i2116; + int i2117; + int i2118; + int i2119; + int i2120; + int i2121; + int i2122; + int i2123; + int i2124; + int i2125; + int i2126; + int i2127; + int i2128; + int i2129; + int i2130; + int i2131; + int i2132; + int i2133; + int i2134; + int i2135; + int i2136; + int i2137; + int i2138; + int i2139; + int i2140; + int i2141; + int i2142; + int i2143; + int i2144; + int i2145; + int i2146; + int i2147; + int i2148; + int i2149; + int i2150; + int i2151; + int i2152; + int i2153; + int i2154; + int i2155; + int i2156; + int i2157; + int i2158; + int i2159; + int i2160; + int i2161; + int i2162; + int i2163; + int i2164; + int i2165; + int i2166; + int i2167; + int i2168; + int i2169; + int i2170; + int i2171; + int i2172; + int i2173; + int i2174; + int i2175; + int i2176; + int i2177; + int i2178; + int i2179; + int i2180; + int i2181; + int i2182; + int i2183; + int i2184; + int i2185; + int i2186; + int i2187; + int i2188; + int i2189; + int i2190; + int i2191; + int i2192; + int i2193; + int i2194; + int i2195; + int i2196; + int i2197; + int i2198; + int i2199; + int i2200; + int i2201; + int i2202; + int i2203; + int i2204; + int i2205; + int i2206; + int i2207; + int i2208; + int i2209; + int i2210; + int i2211; + int i2212; + int i2213; + int i2214; + int i2215; + int i2216; + int i2217; + int i2218; + int i2219; + int i2220; + int i2221; + int i2222; + int i2223; + int i2224; + int i2225; + int i2226; + int i2227; + int i2228; + int i2229; + int i2230; + int i2231; + int i2232; + int i2233; + int i2234; + int i2235; + int i2236; + int i2237; + int i2238; + int i2239; + int i2240; + int i2241; + int i2242; + int i2243; + int i2244; + int i2245; + int i2246; + int i2247; + int i2248; + int i2249; + int i2250; + int i2251; + int i2252; + int i2253; + int i2254; + int i2255; + int i2256; + int i2257; + int i2258; + int i2259; + int i2260; + int i2261; + int i2262; + int i2263; + int i2264; + int i2265; + int i2266; + int i2267; + int i2268; + int i2269; + int i2270; + int i2271; + int i2272; + int i2273; + int i2274; + int i2275; + int i2276; + int i2277; + int i2278; + int i2279; + int i2280; + int i2281; + int i2282; + int i2283; + int i2284; + int i2285; + int i2286; + int i2287; + int i2288; + int i2289; + int i2290; + int i2291; + int i2292; + int i2293; + int i2294; + int i2295; + int i2296; + int i2297; + int i2298; + int i2299; + int i2300; + int i2301; + int i2302; + int i2303; + int i2304; + int i2305; + int i2306; + int i2307; + int i2308; + int i2309; + int i2310; + int i2311; + int i2312; + int i2313; + int i2314; + int i2315; + int i2316; + int i2317; + int i2318; + int i2319; + int i2320; + int i2321; + int i2322; + int i2323; + int i2324; + int i2325; + int i2326; + int i2327; + int i2328; + int i2329; + int i2330; + int i2331; + int i2332; + int i2333; + int i2334; + int i2335; + int i2336; + int i2337; + int i2338; + int i2339; + int i2340; + int i2341; + int i2342; + int i2343; + int i2344; + int i2345; + int i2346; + int i2347; + int i2348; + int i2349; + int i2350; + int i2351; + int i2352; + int i2353; + int i2354; + int i2355; + int i2356; + int i2357; + int i2358; + int i2359; + int i2360; + int i2361; + int i2362; + int i2363; + int i2364; + int i2365; + int i2366; + int i2367; + int i2368; + int i2369; + int i2370; + int i2371; + int i2372; + int i2373; + int i2374; + int i2375; + int i2376; + int i2377; + int i2378; + int i2379; + int i2380; + int i2381; + int i2382; + int i2383; + int i2384; + int i2385; + int i2386; + int i2387; + int i2388; + int i2389; + int i2390; + int i2391; + int i2392; + int i2393; + int i2394; + int i2395; + int i2396; + int i2397; + int i2398; + int i2399; + int i2400; + int i2401; + int i2402; + int i2403; + int i2404; + int i2405; + int i2406; + int i2407; + int i2408; + int i2409; + int i2410; + int i2411; + int i2412; + int i2413; + int i2414; + int i2415; + int i2416; + int i2417; + int i2418; + int i2419; + int i2420; + int i2421; + int i2422; + int i2423; + int i2424; + int i2425; + int i2426; + int i2427; + int i2428; + int i2429; + int i2430; + int i2431; + int i2432; + int i2433; + int i2434; + int i2435; + int i2436; + int i2437; + int i2438; + int i2439; + int i2440; + int i2441; + int i2442; + int i2443; + int i2444; + int i2445; + int i2446; + int i2447; + int i2448; + int i2449; + int i2450; + int i2451; + int i2452; + int i2453; + int i2454; + int i2455; + int i2456; + int i2457; + int i2458; + int i2459; + int i2460; + int i2461; + int i2462; + int i2463; + int i2464; + int i2465; + int i2466; + int i2467; + int i2468; + int i2469; + int i2470; + int i2471; + int i2472; + int i2473; + int i2474; + int i2475; + int i2476; + int i2477; + int i2478; + int i2479; + int i2480; + int i2481; + int i2482; + int i2483; + int i2484; + int i2485; + int i2486; + int i2487; + int i2488; + int i2489; + int i2490; + int i2491; + int i2492; + int i2493; + int i2494; + int i2495; + int i2496; + int i2497; + int i2498; + int i2499; + int i2500; + int i2501; + int i2502; + int i2503; + int i2504; + int i2505; + int i2506; + int i2507; + int i2508; + int i2509; + int i2510; + int i2511; + int i2512; + int i2513; + int i2514; + int i2515; + int i2516; + int i2517; + int i2518; + int i2519; + int i2520; + int i2521; + int i2522; + int i2523; + int i2524; + int i2525; + int i2526; + int i2527; + int i2528; + int i2529; + int i2530; + int i2531; + int i2532; + int i2533; + int i2534; + int i2535; + int i2536; + int i2537; + int i2538; + int i2539; + int i2540; + int i2541; + int i2542; + int i2543; + int i2544; + int i2545; + int i2546; + int i2547; + int i2548; + int i2549; + int i2550; + int i2551; + int i2552; + int i2553; + int i2554; + int i2555; + int i2556; + int i2557; + int i2558; + int i2559; + int i2560; + int i2561; + int i2562; + int i2563; + int i2564; + int i2565; + int i2566; + int i2567; + int i2568; + int i2569; + int i2570; + int i2571; + int i2572; + int i2573; + int i2574; + int i2575; + int i2576; + int i2577; + int i2578; + int i2579; + int i2580; + int i2581; + int i2582; + int i2583; + int i2584; + int i2585; + int i2586; + int i2587; + int i2588; + int i2589; + int i2590; + int i2591; + int i2592; + int i2593; + int i2594; + int i2595; + int i2596; + int i2597; + int i2598; + int i2599; + int i2600; + int i2601; + int i2602; + int i2603; + int i2604; + int i2605; + int i2606; + int i2607; + int i2608; + int i2609; + int i2610; + int i2611; + int i2612; + int i2613; + int i2614; + int i2615; + int i2616; + int i2617; + int i2618; + int i2619; + int i2620; + int i2621; + int i2622; + int i2623; + int i2624; + int i2625; + int i2626; + int i2627; + int i2628; + int i2629; + int i2630; + int i2631; + int i2632; + int i2633; + int i2634; + int i2635; + int i2636; + int i2637; + int i2638; + int i2639; + int i2640; + int i2641; + int i2642; + int i2643; + int i2644; + int i2645; + int i2646; + int i2647; + int i2648; + int i2649; + int i2650; + int i2651; + int i2652; + int i2653; + int i2654; + int i2655; + int i2656; + int i2657; + int i2658; + int i2659; + int i2660; + int i2661; + int i2662; + int i2663; + int i2664; + int i2665; + int i2666; + int i2667; + int i2668; + int i2669; + int i2670; + int i2671; + int i2672; + int i2673; + int i2674; + int i2675; + int i2676; + int i2677; + int i2678; + int i2679; + int i2680; + int i2681; + int i2682; + int i2683; + int i2684; + int i2685; + int i2686; + int i2687; + int i2688; + int i2689; + int i2690; + int i2691; + int i2692; + int i2693; + int i2694; + int i2695; + int i2696; + int i2697; + int i2698; + int i2699; + int i2700; + int i2701; + int i2702; + int i2703; + int i2704; + int i2705; + int i2706; + int i2707; + int i2708; + int i2709; + int i2710; + int i2711; + int i2712; + int i2713; + int i2714; + int i2715; + int i2716; + int i2717; + int i2718; + int i2719; + int i2720; + int i2721; + int i2722; + int i2723; + int i2724; + int i2725; + int i2726; + int i2727; + int i2728; + int i2729; + int i2730; + int i2731; + int i2732; + int i2733; + int i2734; + int i2735; + int i2736; + int i2737; + int i2738; + int i2739; + int i2740; + int i2741; + int i2742; + int i2743; + int i2744; + int i2745; + int i2746; + int i2747; + int i2748; + int i2749; + int i2750; + int i2751; + int i2752; + int i2753; + int i2754; + int i2755; + int i2756; + int i2757; + int i2758; + int i2759; + int i2760; + int i2761; + int i2762; + int i2763; + int i2764; + int i2765; + int i2766; + int i2767; + int i2768; + int i2769; + int i2770; + int i2771; + int i2772; + int i2773; + int i2774; + int i2775; + int i2776; + int i2777; + int i2778; + int i2779; + int i2780; + int i2781; + int i2782; + int i2783; + int i2784; + int i2785; + int i2786; + int i2787; + int i2788; + int i2789; + int i2790; + int i2791; + int i2792; + int i2793; + int i2794; + int i2795; + int i2796; + int i2797; + int i2798; + int i2799; + int i2800; + int i2801; + int i2802; + int i2803; + int i2804; + int i2805; + int i2806; + int i2807; + int i2808; + int i2809; + int i2810; + int i2811; + int i2812; + int i2813; + int i2814; + int i2815; + int i2816; + int i2817; + int i2818; + int i2819; + int i2820; + int i2821; + int i2822; + int i2823; + int i2824; + int i2825; + int i2826; + int i2827; + int i2828; + int i2829; + int i2830; + int i2831; + int i2832; + int i2833; + int i2834; + int i2835; + int i2836; + int i2837; + int i2838; + int i2839; + int i2840; + int i2841; + int i2842; + int i2843; + int i2844; + int i2845; + int i2846; + int i2847; + int i2848; + int i2849; + int i2850; + int i2851; + int i2852; + int i2853; + int i2854; + int i2855; + int i2856; + int i2857; + int i2858; + int i2859; + int i2860; + int i2861; + int i2862; + int i2863; + int i2864; + int i2865; + int i2866; + int i2867; + int i2868; + int i2869; + int i2870; + int i2871; + int i2872; + int i2873; + int i2874; + int i2875; + int i2876; + int i2877; + int i2878; + int i2879; + int i2880; + int i2881; + int i2882; + int i2883; + int i2884; + int i2885; + int i2886; + int i2887; + int i2888; + int i2889; + int i2890; + int i2891; + int i2892; + int i2893; + int i2894; + int i2895; + int i2896; + int i2897; + int i2898; + int i2899; + int i2900; + int i2901; + int i2902; + int i2903; + int i2904; + int i2905; + int i2906; + int i2907; + int i2908; + int i2909; + int i2910; + int i2911; + int i2912; + int i2913; + int i2914; + int i2915; + int i2916; + int i2917; + int i2918; + int i2919; + int i2920; + int i2921; + int i2922; + int i2923; + int i2924; + int i2925; + int i2926; + int i2927; + int i2928; + int i2929; + int i2930; + int i2931; + int i2932; + int i2933; + int i2934; + int i2935; + int i2936; + int i2937; + int i2938; + int i2939; + int i2940; + int i2941; + int i2942; + int i2943; + int i2944; + int i2945; + int i2946; + int i2947; + int i2948; + int i2949; + int i2950; + int i2951; + int i2952; + int i2953; + int i2954; + int i2955; + int i2956; + int i2957; + int i2958; + int i2959; + int i2960; + int i2961; + int i2962; + int i2963; + int i2964; + int i2965; + int i2966; + int i2967; + int i2968; + int i2969; + int i2970; + int i2971; + int i2972; + int i2973; + int i2974; + int i2975; + int i2976; + int i2977; + int i2978; + int i2979; + int i2980; + int i2981; + int i2982; + int i2983; + int i2984; + int i2985; + int i2986; + int i2987; + int i2988; + int i2989; + int i2990; + int i2991; + int i2992; + int i2993; + int i2994; + int i2995; + int i2996; + int i2997; + int i2998; + int i2999; + int i3000; + int i3001; + int i3002; + int i3003; + int i3004; + int i3005; + int i3006; + int i3007; + int i3008; + int i3009; + int i3010; + int i3011; + int i3012; + int i3013; + int i3014; + int i3015; + int i3016; + int i3017; + int i3018; + int i3019; + int i3020; + int i3021; + int i3022; + int i3023; + int i3024; + int i3025; + int i3026; + int i3027; + int i3028; + int i3029; + int i3030; + int i3031; + int i3032; + int i3033; + int i3034; + int i3035; + int i3036; + int i3037; + int i3038; + int i3039; + int i3040; + int i3041; + int i3042; + int i3043; + int i3044; + int i3045; + int i3046; + int i3047; + int i3048; + int i3049; + int i3050; + int i3051; + int i3052; + int i3053; + int i3054; + int i3055; + int i3056; + int i3057; + int i3058; + int i3059; + int i3060; + int i3061; + int i3062; + int i3063; + int i3064; + int i3065; + int i3066; + int i3067; + int i3068; + int i3069; + int i3070; + int i3071; + int i3072; + int i3073; + int i3074; + int i3075; + int i3076; + int i3077; + int i3078; + int i3079; + int i3080; + int i3081; + int i3082; + int i3083; + int i3084; + int i3085; + int i3086; + int i3087; + int i3088; + int i3089; + int i3090; + int i3091; + int i3092; + int i3093; + int i3094; + int i3095; + int i3096; + int i3097; + int i3098; + int i3099; + int i3100; + int i3101; + int i3102; + int i3103; + int i3104; + int i3105; + int i3106; + int i3107; + int i3108; + int i3109; + int i3110; + int i3111; + int i3112; + int i3113; + int i3114; + int i3115; + int i3116; + int i3117; + int i3118; + int i3119; + int i3120; + int i3121; + int i3122; + int i3123; + int i3124; + int i3125; + int i3126; + int i3127; + int i3128; + int i3129; + int i3130; + int i3131; + int i3132; + int i3133; + int i3134; + int i3135; + int i3136; + int i3137; + int i3138; + int i3139; + int i3140; + int i3141; + int i3142; + int i3143; + int i3144; + int i3145; + int i3146; + int i3147; + int i3148; + int i3149; + int i3150; + int i3151; + int i3152; + int i3153; + int i3154; + int i3155; + int i3156; + int i3157; + int i3158; + int i3159; + int i3160; + int i3161; + int i3162; + int i3163; + int i3164; + int i3165; + int i3166; + int i3167; + int i3168; + int i3169; + int i3170; + int i3171; + int i3172; + int i3173; + int i3174; + int i3175; + int i3176; + int i3177; + int i3178; + int i3179; + int i3180; + int i3181; + int i3182; + int i3183; + int i3184; + int i3185; + int i3186; + int i3187; + int i3188; + int i3189; + int i3190; + int i3191; + int i3192; + int i3193; + int i3194; + int i3195; + int i3196; + int i3197; + int i3198; + int i3199; + int i3200; + int i3201; + int i3202; + int i3203; + int i3204; + int i3205; + int i3206; + int i3207; + int i3208; + int i3209; + int i3210; + int i3211; + int i3212; + int i3213; + int i3214; + int i3215; + int i3216; + int i3217; + int i3218; + int i3219; + int i3220; + int i3221; + int i3222; + int i3223; + int i3224; + int i3225; + int i3226; + int i3227; + int i3228; + int i3229; + int i3230; + int i3231; + int i3232; + int i3233; + int i3234; + int i3235; + int i3236; + int i3237; + int i3238; + int i3239; + int i3240; + int i3241; + int i3242; + int i3243; + int i3244; + int i3245; + int i3246; + int i3247; + int i3248; + int i3249; + int i3250; + int i3251; + int i3252; + int i3253; + int i3254; + int i3255; + int i3256; + int i3257; + int i3258; + int i3259; + int i3260; + int i3261; + int i3262; + int i3263; + int i3264; + int i3265; + int i3266; + int i3267; + int i3268; + int i3269; + int i3270; + int i3271; + int i3272; + int i3273; + int i3274; + int i3275; + int i3276; + int i3277; + int i3278; + int i3279; + int i3280; + int i3281; + int i3282; + int i3283; + int i3284; + int i3285; + int i3286; + int i3287; + int i3288; + int i3289; + int i3290; + int i3291; + int i3292; + int i3293; + int i3294; + int i3295; + int i3296; + int i3297; + int i3298; + int i3299; + int i3300; + int i3301; + int i3302; + int i3303; + int i3304; + int i3305; + int i3306; + int i3307; + int i3308; + int i3309; + int i3310; + int i3311; + int i3312; + int i3313; + int i3314; + int i3315; + int i3316; + int i3317; + int i3318; + int i3319; + int i3320; + int i3321; + int i3322; + int i3323; + int i3324; + int i3325; + int i3326; + int i3327; + int i3328; + int i3329; + int i3330; + int i3331; + int i3332; + int i3333; + int i3334; + int i3335; + int i3336; + int i3337; + int i3338; + int i3339; + int i3340; + int i3341; + int i3342; + int i3343; + int i3344; + int i3345; + int i3346; + int i3347; + int i3348; + int i3349; + int i3350; + int i3351; + int i3352; + int i3353; + int i3354; + int i3355; + int i3356; + int i3357; + int i3358; + int i3359; + int i3360; + int i3361; + int i3362; + int i3363; + int i3364; + int i3365; + int i3366; + int i3367; + int i3368; + int i3369; + int i3370; + int i3371; + int i3372; + int i3373; + int i3374; + int i3375; + int i3376; + int i3377; + int i3378; + int i3379; + int i3380; + int i3381; + int i3382; + int i3383; + int i3384; + int i3385; + int i3386; + int i3387; + int i3388; + int i3389; + int i3390; + int i3391; + int i3392; + int i3393; + int i3394; + int i3395; + int i3396; + int i3397; + int i3398; + int i3399; + int i3400; + int i3401; + int i3402; + int i3403; + int i3404; + int i3405; + int i3406; + int i3407; + int i3408; + int i3409; + int i3410; + int i3411; + int i3412; + int i3413; + int i3414; + int i3415; + int i3416; + int i3417; + int i3418; + int i3419; + int i3420; + int i3421; + int i3422; + int i3423; + int i3424; + int i3425; + int i3426; + int i3427; + int i3428; + int i3429; + int i3430; + int i3431; + int i3432; + int i3433; + int i3434; + int i3435; + int i3436; + int i3437; + int i3438; + int i3439; + int i3440; + int i3441; + int i3442; + int i3443; + int i3444; + int i3445; + int i3446; + int i3447; + int i3448; + int i3449; + int i3450; + int i3451; + int i3452; + int i3453; + int i3454; + int i3455; + int i3456; + int i3457; + int i3458; + int i3459; + int i3460; + int i3461; + int i3462; + int i3463; + int i3464; + int i3465; + int i3466; + int i3467; + int i3468; + int i3469; + int i3470; + int i3471; + int i3472; + int i3473; + int i3474; + int i3475; + int i3476; + int i3477; + int i3478; + int i3479; + int i3480; + int i3481; + int i3482; + int i3483; + int i3484; + int i3485; + int i3486; + int i3487; + int i3488; + int i3489; + int i3490; + int i3491; + int i3492; + int i3493; + int i3494; + int i3495; + int i3496; + int i3497; + int i3498; + int i3499; + int i3500; + int i3501; + int i3502; + int i3503; + int i3504; + int i3505; + int i3506; + int i3507; + int i3508; + int i3509; + int i3510; + int i3511; + int i3512; + int i3513; + int i3514; + int i3515; + int i3516; + int i3517; + int i3518; + int i3519; + int i3520; + int i3521; + int i3522; + int i3523; + int i3524; + int i3525; + int i3526; + int i3527; + int i3528; + int i3529; + int i3530; + int i3531; + int i3532; + int i3533; + int i3534; + int i3535; + int i3536; + int i3537; + int i3538; + int i3539; + int i3540; + int i3541; + int i3542; + int i3543; + int i3544; + int i3545; + int i3546; + int i3547; + int i3548; + int i3549; + int i3550; + int i3551; + int i3552; + int i3553; + int i3554; + int i3555; + int i3556; + int i3557; + int i3558; + int i3559; + int i3560; + int i3561; + int i3562; + int i3563; + int i3564; + int i3565; + int i3566; + int i3567; + int i3568; + int i3569; + int i3570; + int i3571; + int i3572; + int i3573; + int i3574; + int i3575; + int i3576; + int i3577; + int i3578; + int i3579; + int i3580; + int i3581; + int i3582; + int i3583; + int i3584; + int i3585; + int i3586; + int i3587; + int i3588; + int i3589; + int i3590; + int i3591; + int i3592; + int i3593; + int i3594; + int i3595; + int i3596; + int i3597; + int i3598; + int i3599; + int i3600; + int i3601; + int i3602; + int i3603; + int i3604; + int i3605; + int i3606; + int i3607; + int i3608; + int i3609; + int i3610; + int i3611; + int i3612; + int i3613; + int i3614; + int i3615; + int i3616; + int i3617; + int i3618; + int i3619; + int i3620; + int i3621; + int i3622; + int i3623; + int i3624; + int i3625; + int i3626; + int i3627; + int i3628; + int i3629; + int i3630; + int i3631; + int i3632; + int i3633; + int i3634; + int i3635; + int i3636; + int i3637; + int i3638; + int i3639; + int i3640; + int i3641; + int i3642; + int i3643; + int i3644; + int i3645; + int i3646; + int i3647; + int i3648; + int i3649; + int i3650; + int i3651; + int i3652; + int i3653; + int i3654; + int i3655; + int i3656; + int i3657; + int i3658; + int i3659; + int i3660; + int i3661; + int i3662; + int i3663; + int i3664; + int i3665; + int i3666; + int i3667; + int i3668; + int i3669; + int i3670; + int i3671; + int i3672; + int i3673; + int i3674; + int i3675; + int i3676; + int i3677; + int i3678; + int i3679; + int i3680; + int i3681; + int i3682; + int i3683; + int i3684; + int i3685; + int i3686; + int i3687; + int i3688; + int i3689; + int i3690; + int i3691; + int i3692; + int i3693; + int i3694; + int i3695; + int i3696; + int i3697; + int i3698; + int i3699; + int i3700; + int i3701; + int i3702; + int i3703; + int i3704; + int i3705; + int i3706; + int i3707; + int i3708; + int i3709; + int i3710; + int i3711; + int i3712; + int i3713; + int i3714; + int i3715; + int i3716; + int i3717; + int i3718; + int i3719; + int i3720; + int i3721; + int i3722; + int i3723; + int i3724; + int i3725; + int i3726; + int i3727; + int i3728; + int i3729; + int i3730; + int i3731; + int i3732; + int i3733; + int i3734; + int i3735; + int i3736; + int i3737; + int i3738; + int i3739; + int i3740; + int i3741; + int i3742; + int i3743; + int i3744; + int i3745; + int i3746; + int i3747; + int i3748; + int i3749; + int i3750; + int i3751; + int i3752; + int i3753; + int i3754; + int i3755; + int i3756; + int i3757; + int i3758; + int i3759; + int i3760; + int i3761; + int i3762; + int i3763; + int i3764; + int i3765; + int i3766; + int i3767; + int i3768; + int i3769; + int i3770; + int i3771; + int i3772; + int i3773; + int i3774; + int i3775; + int i3776; + int i3777; + int i3778; + int i3779; + int i3780; + int i3781; + int i3782; + int i3783; + int i3784; + int i3785; + int i3786; + int i3787; + int i3788; + int i3789; + int i3790; + int i3791; + int i3792; + int i3793; + int i3794; + int i3795; + int i3796; + int i3797; + int i3798; + int i3799; + int i3800; + int i3801; + int i3802; + int i3803; + int i3804; + int i3805; + int i3806; + int i3807; + int i3808; + int i3809; + int i3810; + int i3811; + int i3812; + int i3813; + int i3814; + int i3815; + int i3816; + int i3817; + int i3818; + int i3819; + int i3820; + int i3821; + int i3822; + int i3823; + int i3824; + int i3825; + int i3826; + int i3827; + int i3828; + int i3829; + int i3830; + int i3831; + int i3832; + int i3833; + int i3834; + int i3835; + int i3836; + int i3837; + int i3838; + int i3839; + int i3840; + int i3841; + int i3842; + int i3843; + int i3844; + int i3845; + int i3846; + int i3847; + int i3848; + int i3849; + int i3850; + int i3851; + int i3852; + int i3853; + int i3854; + int i3855; + int i3856; + int i3857; + int i3858; + int i3859; + int i3860; + int i3861; + int i3862; + int i3863; + int i3864; + int i3865; + int i3866; + int i3867; + int i3868; + int i3869; + int i3870; + int i3871; + int i3872; + int i3873; + int i3874; + int i3875; + int i3876; + int i3877; + int i3878; + int i3879; + int i3880; + int i3881; + int i3882; + int i3883; + int i3884; + int i3885; + int i3886; + int i3887; + int i3888; + int i3889; + int i3890; + int i3891; + int i3892; + int i3893; + int i3894; + int i3895; + int i3896; + int i3897; + int i3898; + int i3899; + int i3900; + int i3901; + int i3902; + int i3903; + int i3904; + int i3905; + int i3906; + int i3907; + int i3908; + int i3909; + int i3910; + int i3911; + int i3912; + int i3913; + int i3914; + int i3915; + int i3916; + int i3917; + int i3918; + int i3919; + int i3920; + int i3921; + int i3922; + int i3923; + int i3924; + int i3925; + int i3926; + int i3927; + int i3928; + int i3929; + int i3930; + int i3931; + int i3932; + int i3933; + int i3934; + int i3935; + int i3936; + int i3937; + int i3938; + int i3939; + int i3940; + int i3941; + int i3942; + int i3943; + int i3944; + int i3945; + int i3946; + int i3947; + int i3948; + int i3949; + int i3950; + int i3951; + int i3952; + int i3953; + int i3954; + int i3955; + int i3956; + int i3957; + int i3958; + int i3959; + int i3960; + int i3961; + int i3962; + int i3963; + int i3964; + int i3965; + int i3966; + int i3967; + int i3968; + int i3969; + int i3970; + int i3971; + int i3972; + int i3973; + int i3974; + int i3975; + int i3976; + int i3977; + int i3978; + int i3979; + int i3980; + int i3981; + int i3982; + int i3983; + int i3984; + int i3985; + int i3986; + int i3987; + int i3988; + int i3989; + int i3990; + int i3991; + int i3992; + int i3993; + int i3994; + int i3995; + int i3996; + int i3997; + int i3998; + int i3999; + int i4000; + int i4001; + int i4002; + int i4003; + int i4004; + int i4005; + int i4006; + int i4007; + int i4008; + int i4009; + int i4010; + int i4011; + int i4012; + int i4013; + int i4014; + int i4015; + int i4016; + int i4017; + int i4018; + int i4019; + int i4020; + int i4021; + int i4022; + int i4023; + int i4024; + int i4025; + int i4026; + int i4027; + int i4028; + int i4029; + int i4030; + int i4031; + int i4032; + int i4033; + int i4034; + int i4035; + int i4036; + int i4037; + int i4038; + int i4039; + int i4040; + int i4041; + int i4042; + int i4043; + int i4044; + int i4045; + int i4046; + int i4047; + int i4048; + int i4049; + int i4050; + int i4051; + int i4052; + int i4053; + int i4054; + int i4055; + int i4056; + int i4057; + int i4058; + int i4059; + int i4060; + int i4061; + int i4062; + int i4063; + int i4064; + int i4065; + int i4066; + int i4067; + int i4068; + int i4069; + int i4070; + int i4071; + int i4072; + int i4073; + int i4074; + int i4075; + int i4076; + int i4077; + int i4078; + int i4079; + int i4080; + int i4081; + int i4082; + int i4083; + int i4084; + int i4085; + int i4086; + int i4087; + int i4088; + int i4089; + int i4090; + int i4091; + int i4092; + int i4093; + int i4094; + int i4095; + int i4096; + int i4097; + int i4098; + int i4099; + int i4100; + int i4101; + int i4102; + int i4103; + int i4104; + int i4105; + int i4106; + int i4107; + int i4108; + int i4109; + int i4110; + int i4111; + int i4112; + int i4113; + int i4114; + int i4115; + int i4116; + int i4117; + int i4118; + int i4119; + int i4120; + int i4121; + int i4122; + int i4123; + int i4124; + int i4125; + int i4126; + int i4127; + int i4128; + int i4129; + int i4130; + int i4131; + int i4132; + int i4133; + int i4134; + int i4135; + int i4136; + int i4137; + int i4138; + int i4139; + int i4140; + int i4141; + int i4142; + int i4143; + int i4144; + int i4145; + int i4146; + int i4147; + int i4148; + int i4149; + int i4150; + int i4151; + int i4152; + int i4153; + int i4154; + int i4155; + int i4156; + int i4157; + int i4158; + int i4159; + int i4160; + int i4161; + int i4162; + int i4163; + int i4164; + int i4165; + int i4166; + int i4167; + int i4168; + int i4169; + int i4170; + int i4171; + int i4172; + int i4173; + int i4174; + int i4175; + int i4176; + int i4177; + int i4178; + int i4179; + int i4180; + int i4181; + int i4182; + int i4183; + int i4184; + int i4185; + int i4186; + int i4187; + int i4188; + int i4189; + int i4190; + int i4191; + int i4192; + int i4193; + int i4194; + int i4195; + int i4196; + int i4197; + int i4198; + int i4199; + int i4200; + int i4201; + int i4202; + int i4203; + int i4204; + int i4205; + int i4206; + int i4207; + int i4208; + int i4209; + int i4210; + int i4211; + int i4212; + int i4213; + int i4214; + int i4215; + int i4216; + int i4217; + int i4218; + int i4219; + int i4220; + int i4221; + int i4222; + int i4223; + int i4224; + int i4225; + int i4226; + int i4227; + int i4228; + int i4229; + int i4230; + int i4231; + int i4232; + int i4233; + int i4234; + int i4235; + int i4236; + int i4237; + int i4238; + int i4239; + int i4240; + int i4241; + int i4242; + int i4243; + int i4244; + int i4245; + int i4246; + int i4247; + int i4248; + int i4249; + int i4250; + int i4251; + int i4252; + int i4253; + int i4254; + int i4255; + int i4256; + int i4257; + int i4258; + int i4259; + int i4260; + int i4261; + int i4262; + int i4263; + int i4264; + int i4265; + int i4266; + int i4267; + int i4268; + int i4269; + int i4270; + int i4271; + int i4272; + int i4273; + int i4274; + int i4275; + int i4276; + int i4277; + int i4278; + int i4279; + int i4280; + int i4281; + int i4282; + int i4283; + int i4284; + int i4285; + int i4286; + int i4287; + int i4288; + int i4289; + int i4290; + int i4291; + int i4292; + int i4293; + int i4294; + int i4295; + int i4296; + int i4297; + int i4298; + int i4299; + int i4300; + int i4301; + int i4302; + int i4303; + int i4304; + int i4305; + int i4306; + int i4307; + int i4308; + int i4309; + int i4310; + int i4311; + int i4312; + int i4313; + int i4314; + int i4315; + int i4316; + int i4317; + int i4318; + int i4319; + int i4320; + int i4321; + int i4322; + int i4323; + int i4324; + int i4325; + int i4326; + int i4327; + int i4328; + int i4329; + int i4330; + int i4331; + int i4332; + int i4333; + int i4334; + int i4335; + int i4336; + int i4337; + int i4338; + int i4339; + int i4340; + int i4341; + int i4342; + int i4343; + int i4344; + int i4345; + int i4346; + int i4347; + int i4348; + int i4349; + int i4350; + int i4351; + int i4352; + int i4353; + int i4354; + int i4355; + int i4356; + int i4357; + int i4358; + int i4359; + int i4360; + int i4361; + int i4362; + int i4363; + int i4364; + int i4365; + int i4366; + int i4367; + int i4368; + int i4369; + int i4370; + int i4371; + int i4372; + int i4373; + int i4374; + int i4375; + int i4376; + int i4377; + int i4378; + int i4379; + int i4380; + int i4381; + int i4382; + int i4383; + int i4384; + int i4385; + int i4386; + int i4387; + int i4388; + int i4389; + int i4390; + int i4391; + int i4392; + int i4393; + int i4394; + int i4395; + int i4396; + int i4397; + int i4398; + int i4399; + int i4400; + int i4401; + int i4402; + int i4403; + int i4404; + int i4405; + int i4406; + int i4407; + int i4408; + int i4409; + int i4410; + int i4411; + int i4412; + int i4413; + int i4414; + int i4415; + int i4416; + int i4417; + int i4418; + int i4419; + int i4420; + int i4421; + int i4422; + int i4423; + int i4424; + int i4425; + int i4426; + int i4427; + int i4428; + int i4429; + int i4430; + int i4431; + int i4432; + int i4433; + int i4434; + int i4435; + int i4436; + int i4437; + int i4438; + int i4439; + int i4440; + int i4441; + int i4442; + int i4443; + int i4444; + int i4445; + int i4446; + int i4447; + int i4448; + int i4449; + int i4450; + int i4451; + int i4452; + int i4453; + int i4454; + int i4455; + int i4456; + int i4457; + int i4458; + int i4459; + int i4460; + int i4461; + int i4462; + int i4463; + int i4464; + int i4465; + int i4466; + int i4467; + int i4468; + int i4469; + int i4470; + int i4471; + int i4472; + int i4473; + int i4474; + int i4475; + int i4476; + int i4477; + int i4478; + int i4479; + int i4480; + int i4481; + int i4482; + int i4483; + int i4484; + int i4485; + int i4486; + int i4487; + int i4488; + int i4489; + int i4490; + int i4491; + int i4492; + int i4493; + int i4494; + int i4495; + int i4496; + int i4497; + int i4498; + int i4499; + int i4500; + int i4501; + int i4502; + int i4503; + int i4504; + int i4505; + int i4506; + int i4507; + int i4508; + int i4509; + int i4510; + int i4511; + int i4512; + int i4513; + int i4514; + int i4515; + int i4516; + int i4517; + int i4518; + int i4519; + int i4520; + int i4521; + int i4522; + int i4523; + int i4524; + int i4525; + int i4526; + int i4527; + int i4528; + int i4529; + int i4530; + int i4531; + int i4532; + int i4533; + int i4534; + int i4535; + int i4536; + int i4537; + int i4538; + int i4539; + int i4540; + int i4541; + int i4542; + int i4543; + int i4544; + int i4545; + int i4546; + int i4547; + int i4548; + int i4549; + int i4550; + int i4551; + int i4552; + int i4553; + int i4554; + int i4555; + int i4556; + int i4557; + int i4558; + int i4559; + int i4560; + int i4561; + int i4562; + int i4563; + int i4564; + int i4565; + int i4566; + int i4567; + int i4568; + int i4569; + int i4570; + int i4571; + int i4572; + int i4573; + int i4574; + int i4575; + int i4576; + int i4577; + int i4578; + int i4579; + int i4580; + int i4581; + int i4582; + int i4583; + int i4584; + int i4585; + int i4586; + int i4587; + int i4588; + int i4589; + int i4590; + int i4591; + int i4592; + int i4593; + int i4594; + int i4595; + int i4596; + int i4597; + int i4598; + int i4599; + int i4600; + int i4601; + int i4602; + int i4603; + int i4604; + int i4605; + int i4606; + int i4607; + int i4608; + int i4609; + int i4610; + int i4611; + int i4612; + int i4613; + int i4614; + int i4615; + int i4616; + int i4617; + int i4618; + int i4619; + int i4620; + int i4621; + int i4622; + int i4623; + int i4624; + int i4625; + int i4626; + int i4627; + int i4628; + int i4629; + int i4630; + int i4631; + int i4632; + int i4633; + int i4634; + int i4635; + int i4636; + int i4637; + int i4638; + int i4639; + int i4640; + int i4641; + int i4642; + int i4643; + int i4644; + int i4645; + int i4646; + int i4647; + int i4648; + int i4649; + int i4650; + int i4651; + int i4652; + int i4653; + int i4654; + int i4655; + int i4656; + int i4657; + int i4658; + int i4659; + int i4660; + int i4661; + int i4662; + int i4663; + int i4664; + int i4665; + int i4666; + int i4667; + int i4668; + int i4669; + int i4670; + int i4671; + int i4672; + int i4673; + int i4674; + int i4675; + int i4676; + int i4677; + int i4678; + int i4679; + int i4680; + int i4681; + int i4682; + int i4683; + int i4684; + int i4685; + int i4686; + int i4687; + int i4688; + int i4689; + int i4690; + int i4691; + int i4692; + int i4693; + int i4694; + int i4695; + int i4696; + int i4697; + int i4698; + int i4699; + int i4700; + int i4701; + int i4702; + int i4703; + int i4704; + int i4705; + int i4706; + int i4707; + int i4708; + int i4709; + int i4710; + int i4711; + int i4712; + int i4713; + int i4714; + int i4715; + int i4716; + int i4717; + int i4718; + int i4719; + int i4720; + int i4721; + int i4722; + int i4723; + int i4724; + int i4725; + int i4726; + int i4727; + int i4728; + int i4729; + int i4730; + int i4731; + int i4732; + int i4733; + int i4734; + int i4735; + int i4736; + int i4737; + int i4738; + int i4739; + int i4740; + int i4741; + int i4742; + int i4743; + int i4744; + int i4745; + int i4746; + int i4747; + int i4748; + int i4749; + int i4750; + int i4751; + int i4752; + int i4753; + int i4754; + int i4755; + int i4756; + int i4757; + int i4758; + int i4759; + int i4760; + int i4761; + int i4762; + int i4763; + int i4764; + int i4765; + int i4766; + int i4767; + int i4768; + int i4769; + int i4770; + int i4771; + int i4772; + int i4773; + int i4774; + int i4775; + int i4776; + int i4777; + int i4778; + int i4779; + int i4780; + int i4781; + int i4782; + int i4783; + int i4784; + int i4785; + int i4786; + int i4787; + int i4788; + int i4789; + int i4790; + int i4791; + int i4792; + int i4793; + int i4794; + int i4795; + int i4796; + int i4797; + int i4798; + int i4799; + int i4800; + int i4801; + int i4802; + int i4803; + int i4804; + int i4805; + int i4806; + int i4807; + int i4808; + int i4809; + int i4810; + int i4811; + int i4812; + int i4813; + int i4814; + int i4815; + int i4816; + int i4817; + int i4818; + int i4819; + int i4820; + int i4821; + int i4822; + int i4823; + int i4824; + int i4825; + int i4826; + int i4827; + int i4828; + int i4829; + int i4830; + int i4831; + int i4832; + int i4833; + int i4834; + int i4835; + int i4836; + int i4837; + int i4838; + int i4839; + int i4840; + int i4841; + int i4842; + int i4843; + int i4844; + int i4845; + int i4846; + int i4847; + int i4848; + int i4849; + int i4850; + int i4851; + int i4852; + int i4853; + int i4854; + int i4855; + int i4856; + int i4857; + int i4858; + int i4859; + int i4860; + int i4861; + int i4862; + int i4863; + int i4864; + int i4865; + int i4866; + int i4867; + int i4868; + int i4869; + int i4870; + int i4871; + int i4872; + int i4873; + int i4874; + int i4875; + int i4876; + int i4877; + int i4878; + int i4879; + int i4880; + int i4881; + int i4882; + int i4883; + int i4884; + int i4885; + int i4886; + int i4887; + int i4888; + int i4889; + int i4890; + int i4891; + int i4892; + int i4893; + int i4894; + int i4895; + int i4896; + int i4897; + int i4898; + int i4899; + int i4900; + int i4901; + int i4902; + int i4903; + int i4904; + int i4905; + int i4906; + int i4907; + int i4908; + int i4909; + int i4910; + int i4911; + int i4912; + int i4913; + int i4914; + int i4915; + int i4916; + int i4917; + int i4918; + int i4919; + int i4920; + int i4921; + int i4922; + int i4923; + int i4924; + int i4925; + int i4926; + int i4927; + int i4928; + int i4929; + int i4930; + int i4931; + int i4932; + int i4933; + int i4934; + int i4935; + int i4936; + int i4937; + int i4938; + int i4939; + int i4940; + int i4941; + int i4942; + int i4943; + int i4944; + int i4945; + int i4946; + int i4947; + int i4948; + int i4949; + int i4950; + int i4951; + int i4952; + int i4953; + int i4954; + int i4955; + int i4956; + int i4957; + int i4958; + int i4959; + int i4960; + int i4961; + int i4962; + int i4963; + int i4964; + int i4965; + int i4966; + int i4967; + int i4968; + int i4969; + int i4970; + int i4971; + int i4972; + int i4973; + int i4974; + int i4975; + int i4976; + int i4977; + int i4978; + int i4979; + int i4980; + int i4981; + int i4982; + int i4983; + int i4984; + int i4985; + int i4986; + int i4987; + int i4988; + int i4989; + int i4990; + int i4991; + int i4992; + int i4993; + int i4994; + int i4995; + int i4996; + int i4997; + int i4998; + int i4999; + int i5000; + int i5001; + int i5002; + int i5003; + int i5004; + int i5005; + int i5006; + int i5007; + int i5008; + int i5009; + int i5010; + int i5011; + int i5012; + int i5013; + int i5014; + int i5015; + int i5016; + int i5017; + int i5018; + int i5019; + int i5020; + int i5021; + int i5022; + int i5023; + int i5024; + int i5025; + int i5026; + int i5027; + int i5028; + int i5029; + int i5030; + int i5031; + int i5032; + int i5033; + int i5034; + int i5035; + int i5036; + int i5037; + int i5038; + int i5039; + int i5040; + int i5041; + int i5042; + int i5043; + int i5044; + int i5045; + int i5046; + int i5047; + int i5048; + int i5049; + int i5050; + int i5051; + int i5052; + int i5053; + int i5054; + int i5055; + int i5056; + int i5057; + int i5058; + int i5059; + int i5060; + int i5061; + int i5062; + int i5063; + int i5064; + int i5065; + int i5066; + int i5067; + int i5068; + int i5069; + int i5070; + int i5071; + int i5072; + int i5073; + int i5074; + int i5075; + int i5076; + int i5077; + int i5078; + int i5079; + int i5080; + int i5081; + int i5082; + int i5083; + int i5084; + int i5085; + int i5086; + int i5087; + int i5088; + int i5089; + int i5090; + int i5091; + int i5092; + int i5093; + int i5094; + int i5095; + int i5096; + int i5097; + int i5098; + int i5099; + int i5100; + int i5101; + int i5102; + int i5103; + int i5104; + int i5105; + int i5106; + int i5107; + int i5108; + int i5109; + int i5110; + int i5111; + int i5112; + int i5113; + int i5114; + int i5115; + int i5116; + int i5117; + int i5118; + int i5119; + int i5120; + int i5121; + int i5122; + int i5123; + int i5124; + int i5125; + int i5126; + int i5127; + int i5128; + int i5129; + int i5130; + int i5131; + int i5132; + int i5133; + int i5134; + int i5135; + int i5136; + int i5137; + int i5138; + int i5139; + int i5140; + int i5141; + int i5142; + int i5143; + int i5144; + int i5145; + int i5146; + int i5147; + int i5148; + int i5149; + int i5150; + int i5151; + int i5152; + int i5153; + int i5154; + int i5155; + int i5156; + int i5157; + int i5158; + int i5159; + int i5160; + int i5161; + int i5162; + int i5163; + int i5164; + int i5165; + int i5166; + int i5167; + int i5168; + int i5169; + int i5170; + int i5171; + int i5172; + int i5173; + int i5174; + int i5175; + int i5176; + int i5177; + int i5178; + int i5179; + int i5180; + int i5181; + int i5182; + int i5183; + int i5184; + int i5185; + int i5186; + int i5187; + int i5188; + int i5189; + int i5190; + int i5191; + int i5192; + int i5193; + int i5194; + int i5195; + int i5196; + int i5197; + int i5198; + int i5199; + int i5200; + int i5201; + int i5202; + int i5203; + int i5204; + int i5205; + int i5206; + int i5207; + int i5208; + int i5209; + int i5210; + int i5211; + int i5212; + int i5213; + int i5214; + int i5215; + int i5216; + int i5217; + int i5218; + int i5219; + int i5220; + int i5221; + int i5222; + int i5223; + int i5224; + int i5225; + int i5226; + int i5227; + int i5228; + int i5229; + int i5230; + int i5231; + int i5232; + int i5233; + int i5234; + int i5235; + int i5236; + int i5237; + int i5238; + int i5239; + int i5240; + int i5241; + int i5242; + int i5243; + int i5244; + int i5245; + int i5246; + int i5247; + int i5248; + int i5249; + int i5250; + int i5251; + int i5252; + int i5253; + int i5254; + int i5255; + int i5256; + int i5257; + int i5258; + int i5259; + int i5260; + int i5261; + int i5262; + int i5263; + int i5264; + int i5265; + int i5266; + int i5267; + int i5268; + int i5269; + int i5270; + int i5271; + int i5272; + int i5273; + int i5274; + int i5275; + int i5276; + int i5277; + int i5278; + int i5279; + int i5280; + int i5281; + int i5282; + int i5283; + int i5284; + int i5285; + int i5286; + int i5287; + int i5288; + int i5289; + int i5290; + int i5291; + int i5292; + int i5293; + int i5294; + int i5295; + int i5296; + int i5297; + int i5298; + int i5299; + int i5300; + int i5301; + int i5302; + int i5303; + int i5304; + int i5305; + int i5306; + int i5307; + int i5308; + int i5309; + int i5310; + int i5311; + int i5312; + int i5313; + int i5314; + int i5315; + int i5316; + int i5317; + int i5318; + int i5319; + int i5320; + int i5321; + int i5322; + int i5323; + int i5324; + int i5325; + int i5326; + int i5327; + int i5328; + int i5329; + int i5330; + int i5331; + int i5332; + int i5333; + int i5334; + int i5335; + int i5336; + int i5337; + int i5338; + int i5339; + int i5340; + int i5341; + int i5342; + int i5343; + int i5344; + int i5345; + int i5346; + int i5347; + int i5348; + int i5349; + int i5350; + int i5351; + int i5352; + int i5353; + int i5354; + int i5355; + int i5356; + int i5357; + int i5358; + int i5359; + int i5360; + int i5361; + int i5362; + int i5363; + int i5364; + int i5365; + int i5366; + int i5367; + int i5368; + int i5369; + int i5370; + int i5371; + int i5372; + int i5373; + int i5374; + int i5375; + int i5376; + int i5377; + int i5378; + int i5379; + int i5380; + int i5381; + int i5382; + int i5383; + int i5384; + int i5385; + int i5386; + int i5387; + int i5388; + int i5389; + int i5390; + int i5391; + int i5392; + int i5393; + int i5394; + int i5395; + int i5396; + int i5397; + int i5398; + int i5399; + int i5400; + int i5401; + int i5402; + int i5403; + int i5404; + int i5405; + int i5406; + int i5407; + int i5408; + int i5409; + int i5410; + int i5411; + int i5412; + int i5413; + int i5414; + int i5415; + int i5416; + int i5417; + int i5418; + int i5419; + int i5420; + int i5421; + int i5422; + int i5423; + int i5424; + int i5425; + int i5426; + int i5427; + int i5428; + int i5429; + int i5430; + int i5431; + int i5432; + int i5433; + int i5434; + int i5435; + int i5436; + int i5437; + int i5438; + int i5439; + int i5440; + int i5441; + int i5442; + int i5443; + int i5444; + int i5445; + int i5446; + int i5447; + int i5448; + int i5449; + int i5450; + int i5451; + int i5452; + int i5453; + int i5454; + int i5455; + int i5456; + int i5457; + int i5458; + int i5459; + int i5460; + int i5461; + int i5462; + int i5463; + int i5464; + int i5465; + int i5466; + int i5467; + int i5468; + int i5469; + int i5470; + int i5471; + int i5472; + int i5473; + int i5474; + int i5475; + int i5476; + int i5477; + int i5478; + int i5479; + int i5480; + int i5481; + int i5482; + int i5483; + int i5484; + int i5485; + int i5486; + int i5487; + int i5488; + int i5489; + int i5490; + int i5491; + int i5492; + int i5493; + int i5494; + int i5495; + int i5496; + int i5497; + int i5498; + int i5499; + int i5500; + int i5501; + int i5502; + int i5503; + int i5504; + int i5505; + int i5506; + int i5507; + int i5508; + int i5509; + int i5510; + int i5511; + int i5512; + int i5513; + int i5514; + int i5515; + int i5516; + int i5517; + int i5518; + int i5519; + int i5520; + int i5521; + int i5522; + int i5523; + int i5524; + int i5525; + int i5526; + int i5527; + int i5528; + int i5529; + int i5530; + int i5531; + int i5532; + int i5533; + int i5534; + int i5535; + int i5536; + int i5537; + int i5538; + int i5539; + int i5540; + int i5541; + int i5542; + int i5543; + int i5544; + int i5545; + int i5546; + int i5547; + int i5548; + int i5549; + int i5550; + int i5551; + int i5552; + int i5553; + int i5554; + int i5555; + int i5556; + int i5557; + int i5558; + int i5559; + int i5560; + int i5561; + int i5562; + int i5563; + int i5564; + int i5565; + int i5566; + int i5567; + int i5568; + int i5569; + int i5570; + int i5571; + int i5572; + int i5573; + int i5574; + int i5575; + int i5576; + int i5577; + int i5578; + int i5579; + int i5580; + int i5581; + int i5582; + int i5583; + int i5584; + int i5585; + int i5586; + int i5587; + int i5588; + int i5589; + int i5590; + int i5591; + int i5592; + int i5593; + int i5594; + int i5595; + int i5596; + int i5597; + int i5598; + int i5599; + int i5600; + int i5601; + int i5602; + int i5603; + int i5604; + int i5605; + int i5606; + int i5607; + int i5608; + int i5609; + int i5610; + int i5611; + int i5612; + int i5613; + int i5614; + int i5615; + int i5616; + int i5617; + int i5618; + int i5619; + int i5620; + int i5621; + int i5622; + int i5623; + int i5624; + int i5625; + int i5626; + int i5627; + int i5628; + int i5629; + int i5630; + int i5631; + int i5632; + int i5633; + int i5634; + int i5635; + int i5636; + int i5637; + int i5638; + int i5639; + int i5640; + int i5641; + int i5642; + int i5643; + int i5644; + int i5645; + int i5646; + int i5647; + int i5648; + int i5649; + int i5650; + int i5651; + int i5652; + int i5653; + int i5654; + int i5655; + int i5656; + int i5657; + int i5658; + int i5659; + int i5660; + int i5661; + int i5662; + int i5663; + int i5664; + int i5665; + int i5666; + int i5667; + int i5668; + int i5669; + int i5670; + int i5671; + int i5672; + int i5673; + int i5674; + int i5675; + int i5676; + int i5677; + int i5678; + int i5679; + int i5680; + int i5681; + int i5682; + int i5683; + int i5684; + int i5685; + int i5686; + int i5687; + int i5688; + int i5689; + int i5690; + int i5691; + int i5692; + int i5693; + int i5694; + int i5695; + int i5696; + int i5697; + int i5698; + int i5699; + int i5700; + int i5701; + int i5702; + int i5703; + int i5704; + int i5705; + int i5706; + int i5707; + int i5708; + int i5709; + int i5710; + int i5711; + int i5712; + int i5713; + int i5714; + int i5715; + int i5716; + int i5717; + int i5718; + int i5719; + int i5720; + int i5721; + int i5722; + int i5723; + int i5724; + int i5725; + int i5726; + int i5727; + int i5728; + int i5729; + int i5730; + int i5731; + int i5732; + int i5733; + int i5734; + int i5735; + int i5736; + int i5737; + int i5738; + int i5739; + int i5740; + int i5741; + int i5742; + int i5743; + int i5744; + int i5745; + int i5746; + int i5747; + int i5748; + int i5749; + int i5750; + int i5751; + int i5752; + int i5753; + int i5754; + int i5755; + int i5756; + int i5757; + int i5758; + int i5759; + int i5760; + int i5761; + int i5762; + int i5763; + int i5764; + int i5765; + int i5766; + int i5767; + int i5768; + int i5769; + int i5770; + int i5771; + int i5772; + int i5773; + int i5774; + int i5775; + int i5776; + int i5777; + int i5778; + int i5779; + int i5780; + int i5781; + int i5782; + int i5783; + int i5784; + int i5785; + int i5786; + int i5787; + int i5788; + int i5789; + int i5790; + int i5791; + int i5792; + int i5793; + int i5794; + int i5795; + int i5796; + int i5797; + int i5798; + int i5799; + int i5800; + int i5801; + int i5802; + int i5803; + int i5804; + int i5805; + int i5806; + int i5807; + int i5808; + int i5809; + int i5810; + int i5811; + int i5812; + int i5813; + int i5814; + int i5815; + int i5816; + int i5817; + int i5818; + int i5819; + int i5820; + int i5821; + int i5822; + int i5823; + int i5824; + int i5825; + int i5826; + int i5827; + int i5828; + int i5829; + int i5830; + int i5831; + int i5832; + int i5833; + int i5834; + int i5835; + int i5836; + int i5837; + int i5838; + int i5839; + int i5840; + int i5841; + int i5842; + int i5843; + int i5844; + int i5845; + int i5846; + int i5847; + int i5848; + int i5849; + int i5850; + int i5851; + int i5852; + int i5853; + int i5854; + int i5855; + int i5856; + int i5857; + int i5858; + int i5859; + int i5860; + int i5861; + int i5862; + int i5863; + int i5864; + int i5865; + int i5866; + int i5867; + int i5868; + int i5869; + int i5870; + int i5871; + int i5872; + int i5873; + int i5874; + int i5875; + int i5876; + int i5877; + int i5878; + int i5879; + int i5880; + int i5881; + int i5882; + int i5883; + int i5884; + int i5885; + int i5886; + int i5887; + int i5888; + int i5889; + int i5890; + int i5891; + int i5892; + int i5893; + int i5894; + int i5895; + int i5896; + int i5897; + int i5898; + int i5899; + int i5900; + int i5901; + int i5902; + int i5903; + int i5904; + int i5905; + int i5906; + int i5907; + int i5908; + int i5909; + int i5910; + int i5911; + int i5912; + int i5913; + int i5914; + int i5915; + int i5916; + int i5917; + int i5918; + int i5919; + int i5920; + int i5921; + int i5922; + int i5923; + int i5924; + int i5925; + int i5926; + int i5927; + int i5928; + int i5929; + int i5930; + int i5931; + int i5932; + int i5933; + int i5934; + int i5935; + int i5936; + int i5937; + int i5938; + int i5939; + int i5940; + int i5941; + int i5942; + int i5943; + int i5944; + int i5945; + int i5946; + int i5947; + int i5948; + int i5949; + int i5950; + int i5951; + int i5952; + int i5953; + int i5954; + int i5955; + int i5956; + int i5957; + int i5958; + int i5959; + int i5960; + int i5961; + int i5962; + int i5963; + int i5964; + int i5965; + int i5966; + int i5967; + int i5968; + int i5969; + int i5970; + int i5971; + int i5972; + int i5973; + int i5974; + int i5975; + int i5976; + int i5977; + int i5978; + int i5979; + int i5980; + int i5981; + int i5982; + int i5983; + int i5984; + int i5985; + int i5986; + int i5987; + int i5988; + int i5989; + int i5990; + int i5991; + int i5992; + int i5993; + int i5994; + int i5995; + int i5996; + int i5997; + int i5998; + int i5999; + int i6000; + int i6001; + int i6002; + int i6003; + int i6004; + int i6005; + int i6006; + int i6007; + int i6008; + int i6009; + int i6010; + int i6011; + int i6012; + int i6013; + int i6014; + int i6015; + int i6016; + int i6017; + int i6018; + int i6019; + int i6020; + int i6021; + int i6022; + int i6023; + int i6024; + int i6025; + int i6026; + int i6027; + int i6028; + int i6029; + int i6030; + int i6031; + int i6032; + int i6033; + int i6034; + int i6035; + int i6036; + int i6037; + int i6038; + int i6039; + int i6040; + int i6041; + int i6042; + int i6043; + int i6044; + int i6045; + int i6046; + int i6047; + int i6048; + int i6049; + int i6050; + int i6051; + int i6052; + int i6053; + int i6054; + int i6055; + int i6056; + int i6057; + int i6058; + int i6059; + int i6060; + int i6061; + int i6062; + int i6063; + int i6064; + int i6065; + int i6066; + int i6067; + int i6068; + int i6069; + int i6070; + int i6071; + int i6072; + int i6073; + int i6074; + int i6075; + int i6076; + int i6077; + int i6078; + int i6079; + int i6080; + int i6081; + int i6082; + int i6083; + int i6084; + int i6085; + int i6086; + int i6087; + int i6088; + int i6089; + int i6090; + int i6091; + int i6092; + int i6093; + int i6094; + int i6095; + int i6096; + int i6097; + int i6098; + int i6099; + int i6100; + int i6101; + int i6102; + int i6103; + int i6104; + int i6105; + int i6106; + int i6107; + int i6108; + int i6109; + int i6110; + int i6111; + int i6112; + int i6113; + int i6114; + int i6115; + int i6116; + int i6117; + int i6118; + int i6119; + int i6120; + int i6121; + int i6122; + int i6123; + int i6124; + int i6125; + int i6126; + int i6127; + int i6128; + int i6129; + int i6130; + int i6131; + int i6132; + int i6133; + int i6134; + int i6135; + int i6136; + int i6137; + int i6138; + int i6139; + int i6140; + int i6141; + int i6142; + int i6143; + int i6144; + int i6145; + int i6146; + int i6147; + int i6148; + int i6149; + int i6150; + int i6151; + int i6152; + int i6153; + int i6154; + int i6155; + int i6156; + int i6157; + int i6158; + int i6159; + int i6160; + int i6161; + int i6162; + int i6163; + int i6164; + int i6165; + int i6166; + int i6167; + int i6168; + int i6169; + int i6170; + int i6171; + int i6172; + int i6173; + int i6174; + int i6175; + int i6176; + int i6177; + int i6178; + int i6179; + int i6180; + int i6181; + int i6182; + int i6183; + int i6184; + int i6185; + int i6186; + int i6187; + int i6188; + int i6189; + int i6190; + int i6191; + int i6192; + int i6193; + int i6194; + int i6195; + int i6196; + int i6197; + int i6198; + int i6199; + int i6200; + int i6201; + int i6202; + int i6203; + int i6204; + int i6205; + int i6206; + int i6207; + int i6208; + int i6209; + int i6210; + int i6211; + int i6212; + int i6213; + int i6214; + int i6215; + int i6216; + int i6217; + int i6218; + int i6219; + int i6220; + int i6221; + int i6222; + int i6223; + int i6224; + int i6225; + int i6226; + int i6227; + int i6228; + int i6229; + int i6230; + int i6231; + int i6232; + int i6233; + int i6234; + int i6235; + int i6236; + int i6237; + int i6238; + int i6239; + int i6240; + int i6241; + int i6242; + int i6243; + int i6244; + int i6245; + int i6246; + int i6247; + int i6248; + int i6249; + int i6250; + int i6251; + int i6252; + int i6253; + int i6254; + int i6255; + int i6256; + int i6257; + int i6258; + int i6259; + int i6260; + int i6261; + int i6262; + int i6263; + int i6264; + int i6265; + int i6266; + int i6267; + int i6268; + int i6269; + int i6270; + int i6271; + int i6272; + int i6273; + int i6274; + int i6275; + int i6276; + int i6277; + int i6278; + int i6279; + int i6280; + int i6281; + int i6282; + int i6283; + int i6284; + int i6285; + int i6286; + int i6287; + int i6288; + int i6289; + int i6290; + int i6291; + int i6292; + int i6293; + int i6294; + int i6295; + int i6296; + int i6297; + int i6298; + int i6299; + int i6300; + int i6301; + int i6302; + int i6303; + int i6304; + int i6305; + int i6306; + int i6307; + int i6308; + int i6309; + int i6310; + int i6311; + int i6312; + int i6313; + int i6314; + int i6315; + int i6316; + int i6317; + int i6318; + int i6319; + int i6320; + int i6321; + int i6322; + int i6323; + int i6324; + int i6325; + int i6326; + int i6327; + int i6328; + int i6329; + int i6330; + int i6331; + int i6332; + int i6333; + int i6334; + int i6335; + int i6336; + int i6337; + int i6338; + int i6339; + int i6340; + int i6341; + int i6342; + int i6343; + int i6344; + int i6345; + int i6346; + int i6347; + int i6348; + int i6349; + int i6350; + int i6351; + int i6352; + int i6353; + int i6354; + int i6355; + int i6356; + int i6357; + int i6358; + int i6359; + int i6360; + int i6361; + int i6362; + int i6363; + int i6364; + int i6365; + int i6366; + int i6367; + int i6368; + int i6369; + int i6370; + int i6371; + int i6372; + int i6373; + int i6374; + int i6375; + int i6376; + int i6377; + int i6378; + int i6379; + int i6380; + int i6381; + int i6382; + int i6383; + int i6384; + int i6385; + int i6386; + int i6387; + int i6388; + int i6389; + int i6390; + int i6391; + int i6392; + int i6393; + int i6394; + int i6395; + int i6396; + int i6397; + int i6398; + int i6399; + int i6400; + int i6401; + int i6402; + int i6403; + int i6404; + int i6405; + int i6406; + int i6407; + int i6408; + int i6409; + int i6410; + int i6411; + int i6412; + int i6413; + int i6414; + int i6415; + int i6416; + int i6417; + int i6418; + int i6419; + int i6420; + int i6421; + int i6422; + int i6423; + int i6424; + int i6425; + int i6426; + int i6427; + int i6428; + int i6429; + int i6430; + int i6431; + int i6432; + int i6433; + int i6434; + int i6435; + int i6436; + int i6437; + int i6438; + int i6439; + int i6440; + int i6441; + int i6442; + int i6443; + int i6444; + int i6445; + int i6446; + int i6447; + int i6448; + int i6449; + int i6450; + int i6451; + int i6452; + int i6453; + int i6454; + int i6455; + int i6456; + int i6457; + int i6458; + int i6459; + int i6460; + int i6461; + int i6462; + int i6463; + int i6464; + int i6465; + int i6466; + int i6467; + int i6468; + int i6469; + int i6470; + int i6471; + int i6472; + int i6473; + int i6474; + int i6475; + int i6476; + int i6477; + int i6478; + int i6479; + int i6480; + int i6481; + int i6482; + int i6483; + int i6484; + int i6485; + int i6486; + int i6487; + int i6488; + int i6489; + int i6490; + int i6491; + int i6492; + int i6493; + int i6494; + int i6495; + int i6496; + int i6497; + int i6498; + int i6499; + int i6500; + int i6501; + int i6502; + int i6503; + int i6504; + int i6505; + int i6506; + int i6507; + int i6508; + int i6509; + int i6510; + int i6511; + int i6512; + int i6513; + int i6514; + int i6515; + int i6516; + int i6517; + int i6518; + int i6519; + int i6520; + int i6521; + int i6522; + int i6523; + int i6524; + int i6525; + int i6526; + int i6527; + int i6528; + int i6529; + int i6530; + int i6531; + int i6532; + int i6533; + int i6534; + int i6535; + int i6536; + int i6537; + int i6538; + int i6539; + int i6540; + int i6541; + int i6542; + int i6543; + int i6544; + int i6545; + int i6546; + int i6547; + int i6548; + int i6549; + int i6550; + int i6551; + int i6552; + int i6553; + int i6554; + int i6555; + int i6556; + int i6557; + int i6558; + int i6559; + int i6560; + int i6561; + int i6562; + int i6563; + int i6564; + int i6565; + int i6566; + int i6567; + int i6568; + int i6569; + int i6570; + int i6571; + int i6572; + int i6573; + int i6574; + int i6575; + int i6576; + int i6577; + int i6578; + int i6579; + int i6580; + int i6581; + int i6582; + int i6583; + int i6584; + int i6585; + int i6586; + int i6587; + int i6588; + int i6589; + int i6590; + int i6591; + int i6592; + int i6593; + int i6594; + int i6595; + int i6596; + int i6597; + int i6598; + int i6599; + int i6600; + int i6601; + int i6602; + int i6603; + int i6604; + int i6605; + int i6606; + int i6607; + int i6608; + int i6609; + int i6610; + int i6611; + int i6612; + int i6613; + int i6614; + int i6615; + int i6616; + int i6617; + int i6618; + int i6619; + int i6620; + int i6621; + int i6622; + int i6623; + int i6624; + int i6625; + int i6626; + int i6627; + int i6628; + int i6629; + int i6630; + int i6631; + int i6632; + int i6633; + int i6634; + int i6635; + int i6636; + int i6637; + int i6638; + int i6639; + int i6640; + int i6641; + int i6642; + int i6643; + int i6644; + int i6645; + int i6646; + int i6647; + int i6648; + int i6649; + int i6650; + int i6651; + int i6652; + int i6653; + int i6654; + int i6655; + int i6656; + int i6657; + int i6658; + int i6659; + int i6660; + int i6661; + int i6662; + int i6663; + int i6664; + int i6665; + int i6666; + int i6667; + int i6668; + int i6669; + int i6670; + int i6671; + int i6672; + int i6673; + int i6674; + int i6675; + int i6676; + int i6677; + int i6678; + int i6679; + int i6680; + int i6681; + int i6682; + int i6683; + int i6684; + int i6685; + int i6686; + int i6687; + int i6688; + int i6689; + int i6690; + int i6691; + int i6692; + int i6693; + int i6694; + int i6695; + int i6696; + int i6697; + int i6698; + int i6699; + int i6700; + int i6701; + int i6702; + int i6703; + int i6704; + int i6705; + int i6706; + int i6707; + int i6708; + int i6709; + int i6710; + int i6711; + int i6712; + int i6713; + int i6714; + int i6715; + int i6716; + int i6717; + int i6718; + int i6719; + int i6720; + int i6721; + int i6722; + int i6723; + int i6724; + int i6725; + int i6726; + int i6727; + int i6728; + int i6729; + int i6730; + int i6731; + int i6732; + int i6733; + int i6734; + int i6735; + int i6736; + int i6737; + int i6738; + int i6739; + int i6740; + int i6741; + int i6742; + int i6743; + int i6744; + int i6745; + int i6746; + int i6747; + int i6748; + int i6749; + int i6750; + int i6751; + int i6752; + int i6753; + int i6754; + int i6755; + int i6756; + int i6757; + int i6758; + int i6759; + int i6760; + int i6761; + int i6762; + int i6763; + int i6764; + int i6765; + int i6766; + int i6767; + int i6768; + int i6769; + int i6770; + int i6771; + int i6772; + int i6773; + int i6774; + int i6775; + int i6776; + int i6777; + int i6778; + int i6779; + int i6780; + int i6781; + int i6782; + int i6783; + int i6784; + int i6785; + int i6786; + int i6787; + int i6788; + int i6789; + int i6790; + int i6791; + int i6792; + int i6793; + int i6794; + int i6795; + int i6796; + int i6797; + int i6798; + int i6799; + int i6800; + int i6801; + int i6802; + int i6803; + int i6804; + int i6805; + int i6806; + int i6807; + int i6808; + int i6809; + int i6810; + int i6811; + int i6812; + int i6813; + int i6814; + int i6815; + int i6816; + int i6817; + int i6818; + int i6819; + int i6820; + int i6821; + int i6822; + int i6823; + int i6824; + int i6825; + int i6826; + int i6827; + int i6828; + int i6829; + int i6830; + int i6831; + int i6832; + int i6833; + int i6834; + int i6835; + int i6836; + int i6837; + int i6838; + int i6839; + int i6840; + int i6841; + int i6842; + int i6843; + int i6844; + int i6845; + int i6846; + int i6847; + int i6848; + int i6849; + int i6850; + int i6851; + int i6852; + int i6853; + int i6854; + int i6855; + int i6856; + int i6857; + int i6858; + int i6859; + int i6860; + int i6861; + int i6862; + int i6863; + int i6864; + int i6865; + int i6866; + int i6867; + int i6868; + int i6869; + int i6870; + int i6871; + int i6872; + int i6873; + int i6874; + int i6875; + int i6876; + int i6877; + int i6878; + int i6879; + int i6880; + int i6881; + int i6882; + int i6883; + int i6884; + int i6885; + int i6886; + int i6887; + int i6888; + int i6889; + int i6890; + int i6891; + int i6892; + int i6893; + int i6894; + int i6895; + int i6896; + int i6897; + int i6898; + int i6899; + int i6900; + int i6901; + int i6902; + int i6903; + int i6904; + int i6905; + int i6906; + int i6907; + int i6908; + int i6909; + int i6910; + int i6911; + int i6912; + int i6913; + int i6914; + int i6915; + int i6916; + int i6917; + int i6918; + int i6919; + int i6920; + int i6921; + int i6922; + int i6923; + int i6924; + int i6925; + int i6926; + int i6927; + int i6928; + int i6929; + int i6930; + int i6931; + int i6932; + int i6933; + int i6934; + int i6935; + int i6936; + int i6937; + int i6938; + int i6939; + int i6940; + int i6941; + int i6942; + int i6943; + int i6944; + int i6945; + int i6946; + int i6947; + int i6948; + int i6949; + int i6950; + int i6951; + int i6952; + int i6953; + int i6954; + int i6955; + int i6956; + int i6957; + int i6958; + int i6959; + int i6960; + int i6961; + int i6962; + int i6963; + int i6964; + int i6965; + int i6966; + int i6967; + int i6968; + int i6969; + int i6970; + int i6971; + int i6972; + int i6973; + int i6974; + int i6975; + int i6976; + int i6977; + int i6978; + int i6979; + int i6980; + int i6981; + int i6982; + int i6983; + int i6984; + int i6985; + int i6986; + int i6987; + int i6988; + int i6989; + int i6990; + int i6991; + int i6992; + int i6993; + int i6994; + int i6995; + int i6996; + int i6997; + int i6998; + int i6999; + int i7000; + int i7001; + int i7002; + int i7003; + int i7004; + int i7005; + int i7006; + int i7007; + int i7008; + int i7009; + int i7010; + int i7011; + int i7012; + int i7013; + int i7014; + int i7015; + int i7016; + int i7017; + int i7018; + int i7019; + int i7020; + int i7021; + int i7022; + int i7023; + int i7024; + int i7025; + int i7026; + int i7027; + int i7028; + int i7029; + int i7030; + int i7031; + int i7032; + int i7033; + int i7034; + int i7035; + int i7036; + int i7037; + int i7038; + int i7039; + int i7040; + int i7041; + int i7042; + int i7043; + int i7044; + int i7045; + int i7046; + int i7047; + int i7048; + int i7049; + int i7050; + int i7051; + int i7052; + int i7053; + int i7054; + int i7055; + int i7056; + int i7057; + int i7058; + int i7059; + int i7060; + int i7061; + int i7062; + int i7063; + int i7064; + int i7065; + int i7066; + int i7067; + int i7068; + int i7069; + int i7070; + int i7071; + int i7072; + int i7073; + int i7074; + int i7075; + int i7076; + int i7077; + int i7078; + int i7079; + int i7080; + int i7081; + int i7082; + int i7083; + int i7084; + int i7085; + int i7086; + int i7087; + int i7088; + int i7089; + int i7090; + int i7091; + int i7092; + int i7093; + int i7094; + int i7095; + int i7096; + int i7097; + int i7098; + int i7099; + int i7100; + int i7101; + int i7102; + int i7103; + int i7104; + int i7105; + int i7106; + int i7107; + int i7108; + int i7109; + int i7110; + int i7111; + int i7112; + int i7113; + int i7114; + int i7115; + int i7116; + int i7117; + int i7118; + int i7119; + int i7120; + int i7121; + int i7122; + int i7123; + int i7124; + int i7125; + int i7126; + int i7127; + int i7128; + int i7129; + int i7130; + int i7131; + int i7132; + int i7133; + int i7134; + int i7135; + int i7136; + int i7137; + int i7138; + int i7139; + int i7140; + int i7141; + int i7142; + int i7143; + int i7144; + int i7145; + int i7146; + int i7147; + int i7148; + int i7149; + int i7150; + int i7151; + int i7152; + int i7153; + int i7154; + int i7155; + int i7156; + int i7157; + int i7158; + int i7159; + int i7160; + int i7161; + int i7162; + int i7163; + int i7164; + int i7165; + int i7166; + int i7167; + int i7168; + int i7169; + int i7170; + int i7171; + int i7172; + int i7173; + int i7174; + int i7175; + int i7176; + int i7177; + int i7178; + int i7179; + int i7180; + int i7181; + int i7182; + int i7183; + int i7184; + int i7185; + int i7186; + int i7187; + int i7188; + int i7189; + int i7190; + int i7191; + int i7192; + int i7193; + int i7194; + int i7195; + int i7196; + int i7197; + int i7198; + int i7199; + int i7200; + int i7201; + int i7202; + int i7203; + int i7204; + int i7205; + int i7206; + int i7207; + int i7208; + int i7209; + int i7210; + int i7211; + int i7212; + int i7213; + int i7214; + int i7215; + int i7216; + int i7217; + int i7218; + int i7219; + int i7220; + int i7221; + int i7222; + int i7223; + int i7224; + int i7225; + int i7226; + int i7227; + int i7228; + int i7229; + int i7230; + int i7231; + int i7232; + int i7233; + int i7234; + int i7235; + int i7236; + int i7237; + int i7238; + int i7239; + int i7240; + int i7241; + int i7242; + int i7243; + int i7244; + int i7245; + int i7246; + int i7247; + int i7248; + int i7249; + int i7250; + int i7251; + int i7252; + int i7253; + int i7254; + int i7255; + int i7256; + int i7257; + int i7258; + int i7259; + int i7260; + int i7261; + int i7262; + int i7263; + int i7264; + int i7265; + int i7266; + int i7267; + int i7268; + int i7269; + int i7270; + int i7271; + int i7272; + int i7273; + int i7274; + int i7275; + int i7276; + int i7277; + int i7278; + int i7279; + int i7280; + int i7281; + int i7282; + int i7283; + int i7284; + int i7285; + int i7286; + int i7287; + int i7288; + int i7289; + int i7290; + int i7291; + int i7292; + int i7293; + int i7294; + int i7295; + int i7296; + int i7297; + int i7298; + int i7299; + int i7300; + int i7301; + int i7302; + int i7303; + int i7304; + int i7305; + int i7306; + int i7307; + int i7308; + int i7309; + int i7310; + int i7311; + int i7312; + int i7313; + int i7314; + int i7315; + int i7316; + int i7317; + int i7318; + int i7319; + int i7320; + int i7321; + int i7322; + int i7323; + int i7324; + int i7325; + int i7326; + int i7327; + int i7328; + int i7329; + int i7330; + int i7331; + int i7332; + int i7333; + int i7334; + int i7335; + int i7336; + int i7337; + int i7338; + int i7339; + int i7340; + int i7341; + int i7342; + int i7343; + int i7344; + int i7345; + int i7346; + int i7347; + int i7348; + int i7349; + int i7350; + int i7351; + int i7352; + int i7353; + int i7354; + int i7355; + int i7356; + int i7357; + int i7358; + int i7359; + int i7360; + int i7361; + int i7362; + int i7363; + int i7364; + int i7365; + int i7366; + int i7367; + int i7368; + int i7369; + int i7370; + int i7371; + int i7372; + int i7373; + int i7374; + int i7375; + int i7376; + int i7377; + int i7378; + int i7379; + int i7380; + int i7381; + int i7382; + int i7383; + int i7384; + int i7385; + int i7386; + int i7387; + int i7388; + int i7389; + int i7390; + int i7391; + int i7392; + int i7393; + int i7394; + int i7395; + int i7396; + int i7397; + int i7398; + int i7399; + int i7400; + int i7401; + int i7402; + int i7403; + int i7404; + int i7405; + int i7406; + int i7407; + int i7408; + int i7409; + int i7410; + int i7411; + int i7412; + int i7413; + int i7414; + int i7415; + int i7416; + int i7417; + int i7418; + int i7419; + int i7420; + int i7421; + int i7422; + int i7423; + int i7424; + int i7425; + int i7426; + int i7427; + int i7428; + int i7429; + int i7430; + int i7431; + int i7432; + int i7433; + int i7434; + int i7435; + int i7436; + int i7437; + int i7438; + int i7439; + int i7440; + int i7441; + int i7442; + int i7443; + int i7444; + int i7445; + int i7446; + int i7447; + int i7448; + int i7449; + int i7450; + int i7451; + int i7452; + int i7453; + int i7454; + int i7455; + int i7456; + int i7457; + int i7458; + int i7459; + int i7460; + int i7461; + int i7462; + int i7463; + int i7464; + int i7465; + int i7466; + int i7467; + int i7468; + int i7469; + int i7470; + int i7471; + int i7472; + int i7473; + int i7474; + int i7475; + int i7476; + int i7477; + int i7478; + int i7479; + int i7480; + int i7481; + int i7482; + int i7483; + int i7484; + int i7485; + int i7486; + int i7487; + int i7488; + int i7489; + int i7490; + int i7491; + int i7492; + int i7493; + int i7494; + int i7495; + int i7496; + int i7497; + int i7498; + int i7499; + int i7500; + int i7501; + int i7502; + int i7503; + int i7504; + int i7505; + int i7506; + int i7507; + int i7508; + int i7509; + int i7510; + int i7511; + int i7512; + int i7513; + int i7514; + int i7515; + int i7516; + int i7517; + int i7518; + int i7519; + int i7520; + int i7521; + int i7522; + int i7523; + int i7524; + int i7525; + int i7526; + int i7527; + int i7528; + int i7529; + int i7530; + int i7531; + int i7532; + int i7533; + int i7534; + int i7535; + int i7536; + int i7537; + int i7538; + int i7539; + int i7540; + int i7541; + int i7542; + int i7543; + int i7544; + int i7545; + int i7546; + int i7547; + int i7548; + int i7549; + int i7550; + int i7551; + int i7552; + int i7553; + int i7554; + int i7555; + int i7556; + int i7557; + int i7558; + int i7559; + int i7560; + int i7561; + int i7562; + int i7563; + int i7564; + int i7565; + int i7566; + int i7567; + int i7568; + int i7569; + int i7570; + int i7571; + int i7572; + int i7573; + int i7574; + int i7575; + int i7576; + int i7577; + int i7578; + int i7579; + int i7580; + int i7581; + int i7582; + int i7583; + int i7584; + int i7585; + int i7586; + int i7587; + int i7588; + int i7589; + int i7590; + int i7591; + int i7592; + int i7593; + int i7594; + int i7595; + int i7596; + int i7597; + int i7598; + int i7599; + int i7600; + int i7601; + int i7602; + int i7603; + int i7604; + int i7605; + int i7606; + int i7607; + int i7608; + int i7609; + int i7610; + int i7611; + int i7612; + int i7613; + int i7614; + int i7615; + int i7616; + int i7617; + int i7618; + int i7619; + int i7620; + int i7621; + int i7622; + int i7623; + int i7624; + int i7625; + int i7626; + int i7627; + int i7628; + int i7629; + int i7630; + int i7631; + int i7632; + int i7633; + int i7634; + int i7635; + int i7636; + int i7637; + int i7638; + int i7639; + int i7640; + int i7641; + int i7642; + int i7643; + int i7644; + int i7645; + int i7646; + int i7647; + int i7648; + int i7649; + int i7650; + int i7651; + int i7652; + int i7653; + int i7654; + int i7655; + int i7656; + int i7657; + int i7658; + int i7659; + int i7660; + int i7661; + int i7662; + int i7663; + int i7664; + int i7665; + int i7666; + int i7667; + int i7668; + int i7669; + int i7670; + int i7671; + int i7672; + int i7673; + int i7674; + int i7675; + int i7676; + int i7677; + int i7678; + int i7679; + int i7680; + int i7681; + int i7682; + int i7683; + int i7684; + int i7685; + int i7686; + int i7687; + int i7688; + int i7689; + int i7690; + int i7691; + int i7692; + int i7693; + int i7694; + int i7695; + int i7696; + int i7697; + int i7698; + int i7699; + int i7700; + int i7701; + int i7702; + int i7703; + int i7704; + int i7705; + int i7706; + int i7707; + int i7708; + int i7709; + int i7710; + int i7711; + int i7712; + int i7713; + int i7714; + int i7715; + int i7716; + int i7717; + int i7718; + int i7719; + int i7720; + int i7721; + int i7722; + int i7723; + int i7724; + int i7725; + int i7726; + int i7727; + int i7728; + int i7729; + int i7730; + int i7731; + int i7732; + int i7733; + int i7734; + int i7735; + int i7736; + int i7737; + int i7738; + int i7739; + int i7740; + int i7741; + int i7742; + int i7743; + int i7744; + int i7745; + int i7746; + int i7747; + int i7748; + int i7749; + int i7750; + int i7751; + int i7752; + int i7753; + int i7754; + int i7755; + int i7756; + int i7757; + int i7758; + int i7759; + int i7760; + int i7761; + int i7762; + int i7763; + int i7764; + int i7765; + int i7766; + int i7767; + int i7768; + int i7769; + int i7770; + int i7771; + int i7772; + int i7773; + int i7774; + int i7775; + int i7776; + int i7777; + int i7778; + int i7779; + int i7780; + int i7781; + int i7782; + int i7783; + int i7784; + int i7785; + int i7786; + int i7787; + int i7788; + int i7789; + int i7790; + int i7791; + int i7792; + int i7793; + int i7794; + int i7795; + int i7796; + int i7797; + int i7798; + int i7799; + int i7800; + int i7801; + int i7802; + int i7803; + int i7804; + int i7805; + int i7806; + int i7807; + int i7808; + int i7809; + int i7810; + int i7811; + int i7812; + int i7813; + int i7814; + int i7815; + int i7816; + int i7817; + int i7818; + int i7819; + int i7820; + int i7821; + int i7822; + int i7823; + int i7824; + int i7825; + int i7826; + int i7827; + int i7828; + int i7829; + int i7830; + int i7831; + int i7832; + int i7833; + int i7834; + int i7835; + int i7836; + int i7837; + int i7838; + int i7839; + int i7840; + int i7841; + int i7842; + int i7843; + int i7844; + int i7845; + int i7846; + int i7847; + int i7848; + int i7849; + int i7850; + int i7851; + int i7852; + int i7853; + int i7854; + int i7855; + int i7856; + int i7857; + int i7858; + int i7859; + int i7860; + int i7861; + int i7862; + int i7863; + int i7864; + int i7865; + int i7866; + int i7867; + int i7868; + int i7869; + int i7870; + int i7871; + int i7872; + int i7873; + int i7874; + int i7875; + int i7876; + int i7877; + int i7878; + int i7879; + int i7880; + int i7881; + int i7882; + int i7883; + int i7884; + int i7885; + int i7886; + int i7887; + int i7888; + int i7889; + int i7890; + int i7891; + int i7892; + int i7893; + int i7894; + int i7895; + int i7896; + int i7897; + int i7898; + int i7899; + int i7900; + int i7901; + int i7902; + int i7903; + int i7904; + int i7905; + int i7906; + int i7907; + int i7908; + int i7909; + int i7910; + int i7911; + int i7912; + int i7913; + int i7914; + int i7915; + int i7916; + int i7917; + int i7918; + int i7919; + int i7920; + int i7921; + int i7922; + int i7923; + int i7924; + int i7925; + int i7926; + int i7927; + int i7928; + int i7929; + int i7930; + int i7931; + int i7932; + int i7933; + int i7934; + int i7935; + int i7936; + int i7937; + int i7938; + int i7939; + int i7940; + int i7941; + int i7942; + int i7943; + int i7944; + int i7945; + int i7946; + int i7947; + int i7948; + int i7949; + int i7950; + int i7951; + int i7952; + int i7953; + int i7954; + int i7955; + int i7956; + int i7957; + int i7958; + int i7959; + int i7960; + int i7961; + int i7962; + int i7963; + int i7964; + int i7965; + int i7966; + int i7967; + int i7968; + int i7969; + int i7970; + int i7971; + int i7972; + int i7973; + int i7974; + int i7975; + int i7976; + int i7977; + int i7978; + int i7979; + int i7980; + int i7981; + int i7982; + int i7983; + int i7984; + int i7985; + int i7986; + int i7987; + int i7988; + int i7989; + int i7990; + int i7991; + int i7992; + int i7993; + int i7994; + int i7995; + int i7996; + int i7997; + int i7998; + int i7999; + int i8000; + int i8001; + int i8002; + int i8003; + int i8004; + int i8005; + int i8006; + int i8007; + int i8008; + int i8009; + int i8010; + int i8011; + int i8012; + int i8013; + int i8014; + int i8015; + int i8016; + int i8017; + int i8018; + int i8019; + int i8020; + int i8021; + int i8022; + int i8023; + int i8024; + int i8025; + int i8026; + int i8027; + int i8028; + int i8029; + int i8030; + int i8031; + int i8032; + int i8033; + int i8034; + int i8035; + int i8036; + int i8037; + int i8038; + int i8039; + int i8040; + int i8041; + int i8042; + int i8043; + int i8044; + int i8045; + int i8046; + int i8047; + int i8048; + int i8049; + int i8050; + int i8051; + int i8052; + int i8053; + int i8054; + int i8055; + int i8056; + int i8057; + int i8058; + int i8059; + int i8060; + int i8061; + int i8062; + int i8063; + int i8064; + int i8065; + int i8066; + int i8067; + int i8068; + int i8069; + int i8070; + int i8071; + int i8072; + int i8073; + int i8074; + int i8075; + int i8076; + int i8077; + int i8078; + int i8079; + int i8080; + int i8081; + int i8082; + int i8083; + int i8084; + int i8085; + int i8086; + int i8087; + int i8088; + int i8089; + int i8090; + int i8091; + int i8092; + int i8093; + int i8094; + int i8095; + int i8096; + int i8097; + int i8098; + int i8099; + int i8100; + int i8101; + int i8102; + int i8103; + int i8104; + int i8105; + int i8106; + int i8107; + int i8108; + int i8109; + int i8110; + int i8111; + int i8112; + int i8113; + int i8114; + int i8115; + int i8116; + int i8117; + int i8118; + int i8119; + int i8120; + int i8121; + int i8122; + int i8123; + int i8124; + int i8125; + int i8126; + int i8127; + int i8128; + int i8129; + int i8130; + int i8131; + int i8132; + int i8133; + int i8134; + int i8135; + int i8136; + int i8137; + int i8138; + int i8139; + int i8140; + int i8141; + int i8142; + int i8143; + int i8144; + int i8145; + int i8146; + int i8147; + int i8148; + int i8149; + int i8150; + int i8151; + int i8152; + int i8153; + int i8154; + int i8155; + int i8156; + int i8157; + int i8158; + int i8159; + int i8160; + int i8161; + int i8162; + int i8163; + int i8164; + int i8165; + int i8166; + int i8167; + int i8168; + int i8169; + int i8170; + int i8171; + int i8172; + int i8173; + int i8174; + int i8175; + int i8176; + int i8177; + int i8178; + int i8179; + int i8180; + int i8181; + int i8182; + int i8183; + int i8184; + int i8185; + int i8186; + int i8187; + int i8188; + int i8189; + int i8190; + int i8191; + int i8192; + int i8193; + int i8194; + int i8195; + int i8196; + int i8197; + int i8198; + int i8199; + int i8200; + int i8201; + int i8202; + int i8203; + int i8204; + int i8205; + int i8206; + int i8207; + int i8208; + int i8209; + int i8210; + int i8211; + int i8212; + int i8213; + int i8214; + int i8215; + int i8216; + int i8217; + int i8218; + int i8219; + int i8220; + int i8221; + int i8222; + int i8223; + int i8224; + int i8225; + int i8226; + int i8227; + int i8228; + int i8229; + int i8230; + int i8231; + int i8232; + int i8233; + int i8234; + int i8235; + int i8236; + int i8237; + int i8238; + int i8239; + int i8240; + int i8241; + int i8242; + int i8243; + int i8244; + int i8245; + int i8246; + int i8247; + int i8248; + int i8249; + int i8250; + int i8251; + int i8252; + int i8253; + int i8254; + int i8255; + int i8256; + int i8257; + int i8258; + int i8259; + int i8260; + int i8261; + int i8262; + int i8263; + int i8264; + int i8265; + int i8266; + int i8267; + int i8268; + int i8269; + int i8270; + int i8271; + int i8272; + int i8273; + int i8274; + int i8275; + int i8276; + int i8277; + int i8278; + int i8279; + int i8280; + int i8281; + int i8282; + int i8283; + int i8284; + int i8285; + int i8286; + int i8287; + int i8288; + int i8289; + int i8290; + int i8291; + int i8292; + int i8293; + int i8294; + int i8295; + int i8296; + int i8297; + int i8298; + int i8299; + int i8300; + int i8301; + int i8302; + int i8303; + int i8304; + int i8305; + int i8306; + int i8307; + int i8308; + int i8309; + int i8310; + int i8311; + int i8312; + int i8313; + int i8314; + int i8315; + int i8316; + int i8317; + int i8318; + int i8319; + int i8320; + int i8321; + int i8322; + int i8323; + int i8324; + int i8325; + int i8326; + int i8327; + int i8328; + int i8329; + int i8330; + int i8331; + int i8332; + int i8333; + int i8334; + int i8335; + int i8336; + int i8337; + int i8338; + int i8339; + int i8340; + int i8341; + int i8342; + int i8343; + int i8344; + int i8345; + int i8346; + int i8347; + int i8348; + int i8349; + int i8350; + int i8351; + int i8352; + int i8353; + int i8354; + int i8355; + int i8356; + int i8357; + int i8358; + int i8359; + int i8360; + int i8361; + int i8362; + int i8363; + int i8364; + int i8365; + int i8366; + int i8367; + int i8368; + int i8369; + int i8370; + int i8371; + int i8372; + int i8373; + int i8374; + int i8375; + int i8376; + int i8377; + int i8378; + int i8379; + int i8380; + int i8381; + int i8382; + int i8383; + int i8384; + int i8385; + int i8386; + int i8387; + int i8388; + int i8389; + int i8390; + int i8391; + int i8392; + int i8393; + int i8394; + int i8395; + int i8396; + int i8397; + int i8398; + int i8399; + int i8400; + int i8401; + int i8402; + int i8403; + int i8404; + int i8405; + int i8406; + int i8407; + int i8408; + int i8409; + int i8410; + int i8411; + int i8412; + int i8413; + int i8414; + int i8415; + int i8416; + int i8417; + int i8418; + int i8419; + int i8420; + int i8421; + int i8422; + int i8423; + int i8424; + int i8425; + int i8426; + int i8427; + int i8428; + int i8429; + int i8430; + int i8431; + int i8432; + int i8433; + int i8434; + int i8435; + int i8436; + int i8437; + int i8438; + int i8439; + int i8440; + int i8441; + int i8442; + int i8443; + int i8444; + int i8445; + int i8446; + int i8447; + int i8448; + int i8449; + int i8450; + int i8451; + int i8452; + int i8453; + int i8454; + int i8455; + int i8456; + int i8457; + int i8458; + int i8459; + int i8460; + int i8461; + int i8462; + int i8463; + int i8464; + int i8465; + int i8466; + int i8467; + int i8468; + int i8469; + int i8470; + int i8471; + int i8472; + int i8473; + int i8474; + int i8475; + int i8476; + int i8477; + int i8478; + int i8479; + int i8480; + int i8481; + int i8482; + int i8483; + int i8484; + int i8485; + int i8486; + int i8487; + int i8488; + int i8489; + int i8490; + int i8491; + int i8492; + int i8493; + int i8494; + int i8495; + int i8496; + int i8497; + int i8498; + int i8499; + int i8500; + int i8501; + int i8502; + int i8503; + int i8504; + int i8505; + int i8506; + int i8507; + int i8508; + int i8509; + int i8510; + int i8511; + int i8512; + int i8513; + int i8514; + int i8515; + int i8516; + int i8517; + int i8518; + int i8519; + int i8520; + int i8521; + int i8522; + int i8523; + int i8524; + int i8525; + int i8526; + int i8527; + int i8528; + int i8529; + int i8530; + int i8531; + int i8532; + int i8533; + int i8534; + int i8535; + int i8536; + int i8537; + int i8538; + int i8539; + int i8540; + int i8541; + int i8542; + int i8543; + int i8544; + int i8545; + int i8546; + int i8547; + int i8548; + int i8549; + int i8550; + int i8551; + int i8552; + int i8553; + int i8554; + int i8555; + int i8556; + int i8557; + int i8558; + int i8559; + int i8560; + int i8561; + int i8562; + int i8563; + int i8564; + int i8565; + int i8566; + int i8567; + int i8568; + int i8569; + int i8570; + int i8571; + int i8572; + int i8573; + int i8574; + int i8575; + int i8576; + int i8577; + int i8578; + int i8579; + int i8580; + int i8581; + int i8582; + int i8583; + int i8584; + int i8585; + int i8586; + int i8587; + int i8588; + int i8589; + int i8590; + int i8591; + int i8592; + int i8593; + int i8594; + int i8595; + int i8596; + int i8597; + int i8598; + int i8599; + int i8600; + int i8601; + int i8602; + int i8603; + int i8604; + int i8605; + int i8606; + int i8607; + int i8608; + int i8609; + int i8610; + int i8611; + int i8612; + int i8613; + int i8614; + int i8615; + int i8616; + int i8617; + int i8618; + int i8619; + int i8620; + int i8621; + int i8622; + int i8623; + int i8624; + int i8625; + int i8626; + int i8627; + int i8628; + int i8629; + int i8630; + int i8631; + int i8632; + int i8633; + int i8634; + int i8635; + int i8636; + int i8637; + int i8638; + int i8639; + int i8640; + int i8641; + int i8642; + int i8643; + int i8644; + int i8645; + int i8646; + int i8647; + int i8648; + int i8649; + int i8650; + int i8651; + int i8652; + int i8653; + int i8654; + int i8655; + int i8656; + int i8657; + int i8658; + int i8659; + int i8660; + int i8661; + int i8662; + int i8663; + int i8664; + int i8665; + int i8666; + int i8667; + int i8668; + int i8669; + int i8670; + int i8671; + int i8672; + int i8673; + int i8674; + int i8675; + int i8676; + int i8677; + int i8678; + int i8679; + int i8680; + int i8681; + int i8682; + int i8683; + int i8684; + int i8685; + int i8686; + int i8687; + int i8688; + int i8689; + int i8690; + int i8691; + int i8692; + int i8693; + int i8694; + int i8695; + int i8696; + int i8697; + int i8698; + int i8699; + int i8700; + int i8701; + int i8702; + int i8703; + int i8704; + int i8705; + int i8706; + int i8707; + int i8708; + int i8709; + int i8710; + int i8711; + int i8712; + int i8713; + int i8714; + int i8715; + int i8716; + int i8717; + int i8718; + int i8719; + int i8720; + int i8721; + int i8722; + int i8723; + int i8724; + int i8725; + int i8726; + int i8727; + int i8728; + int i8729; + int i8730; + int i8731; + int i8732; + int i8733; + int i8734; + int i8735; + int i8736; + int i8737; + int i8738; + int i8739; + int i8740; + int i8741; + int i8742; + int i8743; + int i8744; + int i8745; + int i8746; + int i8747; + int i8748; + int i8749; + int i8750; + int i8751; + int i8752; + int i8753; + int i8754; + int i8755; + int i8756; + int i8757; + int i8758; + int i8759; + int i8760; + int i8761; + int i8762; + int i8763; + int i8764; + int i8765; + int i8766; + int i8767; + int i8768; + int i8769; + int i8770; + int i8771; + int i8772; + int i8773; + int i8774; + int i8775; + int i8776; + int i8777; + int i8778; + int i8779; + int i8780; + int i8781; + int i8782; + int i8783; + int i8784; + int i8785; + int i8786; + int i8787; + int i8788; + int i8789; + int i8790; + int i8791; + int i8792; + int i8793; + int i8794; + int i8795; + int i8796; + int i8797; + int i8798; + int i8799; + int i8800; + int i8801; + int i8802; + int i8803; + int i8804; + int i8805; + int i8806; + int i8807; + int i8808; + int i8809; + int i8810; + int i8811; + int i8812; + int i8813; + int i8814; + int i8815; + int i8816; + int i8817; + int i8818; + int i8819; + int i8820; + int i8821; + int i8822; + int i8823; + int i8824; + int i8825; + int i8826; + int i8827; + int i8828; + int i8829; + int i8830; + int i8831; + int i8832; + int i8833; + int i8834; + int i8835; + int i8836; + int i8837; + int i8838; + int i8839; + int i8840; + int i8841; + int i8842; + int i8843; + int i8844; + int i8845; + int i8846; + int i8847; + int i8848; + int i8849; + int i8850; + int i8851; + int i8852; + int i8853; + int i8854; + int i8855; + int i8856; + int i8857; + int i8858; + int i8859; + int i8860; + int i8861; + int i8862; + int i8863; + int i8864; + int i8865; + int i8866; + int i8867; + int i8868; + int i8869; + int i8870; + int i8871; + int i8872; + int i8873; + int i8874; + int i8875; + int i8876; + int i8877; + int i8878; + int i8879; + int i8880; + int i8881; + int i8882; + int i8883; + int i8884; + int i8885; + int i8886; + int i8887; + int i8888; + int i8889; + int i8890; + int i8891; + int i8892; + int i8893; + int i8894; + int i8895; + int i8896; + int i8897; + int i8898; + int i8899; + int i8900; + int i8901; + int i8902; + int i8903; + int i8904; + int i8905; + int i8906; + int i8907; + int i8908; + int i8909; + int i8910; + int i8911; + int i8912; + int i8913; + int i8914; + int i8915; + int i8916; + int i8917; + int i8918; + int i8919; + int i8920; + int i8921; + int i8922; + int i8923; + int i8924; + int i8925; + int i8926; + int i8927; + int i8928; + int i8929; + int i8930; + int i8931; + int i8932; + int i8933; + int i8934; + int i8935; + int i8936; + int i8937; + int i8938; + int i8939; + int i8940; + int i8941; + int i8942; + int i8943; + int i8944; + int i8945; + int i8946; + int i8947; + int i8948; + int i8949; + int i8950; + int i8951; + int i8952; + int i8953; + int i8954; + int i8955; + int i8956; + int i8957; + int i8958; + int i8959; + int i8960; + int i8961; + int i8962; + int i8963; + int i8964; + int i8965; + int i8966; + int i8967; + int i8968; + int i8969; + int i8970; + int i8971; + int i8972; + int i8973; + int i8974; + int i8975; + int i8976; + int i8977; + int i8978; + int i8979; + int i8980; + int i8981; + int i8982; + int i8983; + int i8984; + int i8985; + int i8986; + int i8987; + int i8988; + int i8989; + int i8990; + int i8991; + int i8992; + int i8993; + int i8994; + int i8995; + int i8996; + int i8997; + int i8998; + int i8999; + int i9000; + int i9001; + int i9002; + int i9003; + int i9004; + int i9005; + int i9006; + int i9007; + int i9008; + int i9009; + int i9010; + int i9011; + int i9012; + int i9013; + int i9014; + int i9015; + int i9016; + int i9017; + int i9018; + int i9019; + int i9020; + int i9021; + int i9022; + int i9023; + int i9024; + int i9025; + int i9026; + int i9027; + int i9028; + int i9029; + int i9030; + int i9031; + int i9032; + int i9033; + int i9034; + int i9035; + int i9036; + int i9037; + int i9038; + int i9039; + int i9040; + int i9041; + int i9042; + int i9043; + int i9044; + int i9045; + int i9046; + int i9047; + int i9048; + int i9049; + int i9050; + int i9051; + int i9052; + int i9053; + int i9054; + int i9055; + int i9056; + int i9057; + int i9058; + int i9059; + int i9060; + int i9061; + int i9062; + int i9063; + int i9064; + int i9065; + int i9066; + int i9067; + int i9068; + int i9069; + int i9070; + int i9071; + int i9072; + int i9073; + int i9074; + int i9075; + int i9076; + int i9077; + int i9078; + int i9079; + int i9080; + int i9081; + int i9082; + int i9083; + int i9084; + int i9085; + int i9086; + int i9087; + int i9088; + int i9089; + int i9090; + int i9091; + int i9092; + int i9093; + int i9094; + int i9095; + int i9096; + int i9097; + int i9098; + int i9099; + int i9100; + int i9101; + int i9102; + int i9103; + int i9104; + int i9105; + int i9106; + int i9107; + int i9108; + int i9109; + int i9110; + int i9111; + int i9112; + int i9113; + int i9114; + int i9115; + int i9116; + int i9117; + int i9118; + int i9119; + int i9120; + int i9121; + int i9122; + int i9123; + int i9124; + int i9125; + int i9126; + int i9127; + int i9128; + int i9129; + int i9130; + int i9131; + int i9132; + int i9133; + int i9134; + int i9135; + int i9136; + int i9137; + int i9138; + int i9139; + int i9140; + int i9141; + int i9142; + int i9143; + int i9144; + int i9145; + int i9146; + int i9147; + int i9148; + int i9149; + int i9150; + int i9151; + int i9152; + int i9153; + int i9154; + int i9155; + int i9156; + int i9157; + int i9158; + int i9159; + int i9160; + int i9161; + int i9162; + int i9163; + int i9164; + int i9165; + int i9166; + int i9167; + int i9168; + int i9169; + int i9170; + int i9171; + int i9172; + int i9173; + int i9174; + int i9175; + int i9176; + int i9177; + int i9178; + int i9179; + int i9180; + int i9181; + int i9182; + int i9183; + int i9184; + int i9185; + int i9186; + int i9187; + int i9188; + int i9189; + int i9190; + int i9191; + int i9192; + int i9193; + int i9194; + int i9195; + int i9196; + int i9197; + int i9198; + int i9199; + int i9200; + int i9201; + int i9202; + int i9203; + int i9204; + int i9205; + int i9206; + int i9207; + int i9208; + int i9209; + int i9210; + int i9211; + int i9212; + int i9213; + int i9214; + int i9215; + int i9216; + int i9217; + int i9218; + int i9219; + int i9220; + int i9221; + int i9222; + int i9223; + int i9224; + int i9225; + int i9226; + int i9227; + int i9228; + int i9229; + int i9230; + int i9231; + int i9232; + int i9233; + int i9234; + int i9235; + int i9236; + int i9237; + int i9238; + int i9239; + int i9240; + int i9241; + int i9242; + int i9243; + int i9244; + int i9245; + int i9246; + int i9247; + int i9248; + int i9249; + int i9250; + int i9251; + int i9252; + int i9253; + int i9254; + int i9255; + int i9256; + int i9257; + int i9258; + int i9259; + int i9260; + int i9261; + int i9262; + int i9263; + int i9264; + int i9265; + int i9266; + int i9267; + int i9268; + int i9269; + int i9270; + int i9271; + int i9272; + int i9273; + int i9274; + int i9275; + int i9276; + int i9277; + int i9278; + int i9279; + int i9280; + int i9281; + int i9282; + int i9283; + int i9284; + int i9285; + int i9286; + int i9287; + int i9288; + int i9289; + int i9290; + int i9291; + int i9292; + int i9293; + int i9294; + int i9295; + int i9296; + int i9297; + int i9298; + int i9299; + int i9300; + int i9301; + int i9302; + int i9303; + int i9304; + int i9305; + int i9306; + int i9307; + int i9308; + int i9309; + int i9310; + int i9311; + int i9312; + int i9313; + int i9314; + int i9315; + int i9316; + int i9317; + int i9318; + int i9319; + int i9320; + int i9321; + int i9322; + int i9323; + int i9324; + int i9325; + int i9326; + int i9327; + int i9328; + int i9329; + int i9330; + int i9331; + int i9332; + int i9333; + int i9334; + int i9335; + int i9336; + int i9337; + int i9338; + int i9339; + int i9340; + int i9341; + int i9342; + int i9343; + int i9344; + int i9345; + int i9346; + int i9347; + int i9348; + int i9349; + int i9350; + int i9351; + int i9352; + int i9353; + int i9354; + int i9355; + int i9356; + int i9357; + int i9358; + int i9359; + int i9360; + int i9361; + int i9362; + int i9363; + int i9364; + int i9365; + int i9366; + int i9367; + int i9368; + int i9369; + int i9370; + int i9371; + int i9372; + int i9373; + int i9374; + int i9375; + int i9376; + int i9377; + int i9378; + int i9379; + int i9380; + int i9381; + int i9382; + int i9383; + int i9384; + int i9385; + int i9386; + int i9387; + int i9388; + int i9389; + int i9390; + int i9391; + int i9392; + int i9393; + int i9394; + int i9395; + int i9396; + int i9397; + int i9398; + int i9399; + int i9400; + int i9401; + int i9402; + int i9403; + int i9404; + int i9405; + int i9406; + int i9407; + int i9408; + int i9409; + int i9410; + int i9411; + int i9412; + int i9413; + int i9414; + int i9415; + int i9416; + int i9417; + int i9418; + int i9419; + int i9420; + int i9421; + int i9422; + int i9423; + int i9424; + int i9425; + int i9426; + int i9427; + int i9428; + int i9429; + int i9430; + int i9431; + int i9432; + int i9433; + int i9434; + int i9435; + int i9436; + int i9437; + int i9438; + int i9439; + int i9440; + int i9441; + int i9442; + int i9443; + int i9444; + int i9445; + int i9446; + int i9447; + int i9448; + int i9449; + int i9450; + int i9451; + int i9452; + int i9453; + int i9454; + int i9455; + int i9456; + int i9457; + int i9458; + int i9459; + int i9460; + int i9461; + int i9462; + int i9463; + int i9464; + int i9465; + int i9466; + int i9467; + int i9468; + int i9469; + int i9470; + int i9471; + int i9472; + int i9473; + int i9474; + int i9475; + int i9476; + int i9477; + int i9478; + int i9479; + int i9480; + int i9481; + int i9482; + int i9483; + int i9484; + int i9485; + int i9486; + int i9487; + int i9488; + int i9489; + int i9490; + int i9491; + int i9492; + int i9493; + int i9494; + int i9495; + int i9496; + int i9497; + int i9498; + int i9499; + int i9500; + int i9501; + int i9502; + int i9503; + int i9504; + int i9505; + int i9506; + int i9507; + int i9508; + int i9509; + int i9510; + int i9511; + int i9512; + int i9513; + int i9514; + int i9515; + int i9516; + int i9517; + int i9518; + int i9519; + int i9520; + int i9521; + int i9522; + int i9523; + int i9524; + int i9525; + int i9526; + int i9527; + int i9528; + int i9529; + int i9530; + int i9531; + int i9532; + int i9533; + int i9534; + int i9535; + int i9536; + int i9537; + int i9538; + int i9539; + int i9540; + int i9541; + int i9542; + int i9543; + int i9544; + int i9545; + int i9546; + int i9547; + int i9548; + int i9549; + int i9550; + int i9551; + int i9552; + int i9553; + int i9554; + int i9555; + int i9556; + int i9557; + int i9558; + int i9559; + int i9560; + int i9561; + int i9562; + int i9563; + int i9564; + int i9565; + int i9566; + int i9567; + int i9568; + int i9569; + int i9570; + int i9571; + int i9572; + int i9573; + int i9574; + int i9575; + int i9576; + int i9577; + int i9578; + int i9579; + int i9580; + int i9581; + int i9582; + int i9583; + int i9584; + int i9585; + int i9586; + int i9587; + int i9588; + int i9589; + int i9590; + int i9591; + int i9592; + int i9593; + int i9594; + int i9595; + int i9596; + int i9597; + int i9598; + int i9599; + int i9600; + int i9601; + int i9602; + int i9603; + int i9604; + int i9605; + int i9606; + int i9607; + int i9608; + int i9609; + int i9610; + int i9611; + int i9612; + int i9613; + int i9614; + int i9615; + int i9616; + int i9617; + int i9618; + int i9619; + int i9620; + int i9621; + int i9622; + int i9623; + int i9624; + int i9625; + int i9626; + int i9627; + int i9628; + int i9629; + int i9630; + int i9631; + int i9632; + int i9633; + int i9634; + int i9635; + int i9636; + int i9637; + int i9638; + int i9639; + int i9640; + int i9641; + int i9642; + int i9643; + int i9644; + int i9645; + int i9646; + int i9647; + int i9648; + int i9649; + int i9650; + int i9651; + int i9652; + int i9653; + int i9654; + int i9655; + int i9656; + int i9657; + int i9658; + int i9659; + int i9660; + int i9661; + int i9662; + int i9663; + int i9664; + int i9665; + int i9666; + int i9667; + int i9668; + int i9669; + int i9670; + int i9671; + int i9672; + int i9673; + int i9674; + int i9675; + int i9676; + int i9677; + int i9678; + int i9679; + int i9680; + int i9681; + int i9682; + int i9683; + int i9684; + int i9685; + int i9686; + int i9687; + int i9688; + int i9689; + int i9690; + int i9691; + int i9692; + int i9693; + int i9694; + int i9695; + int i9696; + int i9697; + int i9698; + int i9699; + int i9700; + int i9701; + int i9702; + int i9703; + int i9704; + int i9705; + int i9706; + int i9707; + int i9708; + int i9709; + int i9710; + int i9711; + int i9712; + int i9713; + int i9714; + int i9715; + int i9716; + int i9717; + int i9718; + int i9719; + int i9720; + int i9721; + int i9722; + int i9723; + int i9724; + int i9725; + int i9726; + int i9727; + int i9728; + int i9729; + int i9730; + int i9731; + int i9732; + int i9733; + int i9734; + int i9735; + int i9736; + int i9737; + int i9738; + int i9739; + int i9740; + int i9741; + int i9742; + int i9743; + int i9744; + int i9745; + int i9746; + int i9747; + int i9748; + int i9749; + int i9750; + int i9751; + int i9752; + int i9753; + int i9754; + int i9755; + int i9756; + int i9757; + int i9758; + int i9759; + int i9760; + int i9761; + int i9762; + int i9763; + int i9764; + int i9765; + int i9766; + int i9767; + int i9768; + int i9769; + int i9770; + int i9771; + int i9772; + int i9773; + int i9774; + int i9775; + int i9776; + int i9777; + int i9778; + int i9779; + int i9780; + int i9781; + int i9782; + int i9783; + int i9784; + int i9785; + int i9786; + int i9787; + int i9788; + int i9789; + int i9790; + int i9791; + int i9792; + int i9793; + int i9794; + int i9795; + int i9796; + int i9797; + int i9798; + int i9799; + int i9800; + int i9801; + int i9802; + int i9803; + int i9804; + int i9805; + int i9806; + int i9807; + int i9808; + int i9809; + int i9810; + int i9811; + int i9812; + int i9813; + int i9814; + int i9815; + int i9816; + int i9817; + int i9818; + int i9819; + int i9820; + int i9821; + int i9822; + int i9823; + int i9824; + int i9825; + int i9826; + int i9827; + int i9828; + int i9829; + int i9830; + int i9831; + int i9832; + int i9833; + int i9834; + int i9835; + int i9836; + int i9837; + int i9838; + int i9839; + int i9840; + int i9841; + int i9842; + int i9843; + int i9844; + int i9845; + int i9846; + int i9847; + int i9848; + int i9849; + int i9850; + int i9851; + int i9852; + int i9853; + int i9854; + int i9855; + int i9856; + int i9857; + int i9858; + int i9859; + int i9860; + int i9861; + int i9862; + int i9863; + int i9864; + int i9865; + int i9866; + int i9867; + int i9868; + int i9869; + int i9870; + int i9871; + int i9872; + int i9873; + int i9874; + int i9875; + int i9876; + int i9877; + int i9878; + int i9879; + int i9880; + int i9881; + int i9882; + int i9883; + int i9884; + int i9885; + int i9886; + int i9887; + int i9888; + int i9889; + int i9890; + int i9891; + int i9892; + int i9893; + int i9894; + int i9895; + int i9896; + int i9897; + int i9898; + int i9899; + int i9900; + int i9901; + int i9902; + int i9903; + int i9904; + int i9905; + int i9906; + int i9907; + int i9908; + int i9909; + int i9910; + int i9911; + int i9912; + int i9913; + int i9914; + int i9915; + int i9916; + int i9917; + int i9918; + int i9919; + int i9920; + int i9921; + int i9922; + int i9923; + int i9924; + int i9925; + int i9926; + int i9927; + int i9928; + int i9929; + int i9930; + int i9931; + int i9932; + int i9933; + int i9934; + int i9935; + int i9936; + int i9937; + int i9938; + int i9939; + int i9940; + int i9941; + int i9942; + int i9943; + int i9944; + int i9945; + int i9946; + int i9947; + int i9948; + int i9949; + int i9950; + int i9951; + int i9952; + int i9953; + int i9954; + int i9955; + int i9956; + int i9957; + int i9958; + int i9959; + int i9960; + int i9961; + int i9962; + int i9963; + int i9964; + int i9965; + int i9966; + int i9967; + int i9968; + int i9969; + int i9970; + int i9971; + int i9972; + int i9973; + int i9974; + int i9975; + int i9976; + int i9977; + int i9978; + int i9979; + int i9980; + int i9981; + int i9982; + int i9983; + int i9984; + int i9985; + int i9986; + int i9987; + int i9988; + int i9989; + int i9990; + int i9991; + int i9992; + int i9993; + int i9994; + int i9995; + int i9996; + int i9997; + int i9998; + int i9999; + int i10000; + int i10001; + int i10002; + int i10003; + int i10004; + int i10005; + int i10006; + int i10007; + int i10008; + int i10009; + int i10010; + int i10011; + int i10012; + int i10013; + int i10014; + int i10015; + int i10016; + int i10017; + int i10018; + int i10019; + int i10020; + int i10021; + int i10022; + int i10023; + int i10024; + int i10025; + int i10026; + int i10027; + int i10028; + int i10029; + int i10030; + int i10031; + int i10032; + int i10033; + int i10034; + int i10035; + int i10036; + int i10037; + int i10038; + int i10039; + int i10040; + int i10041; + int i10042; + int i10043; + int i10044; + int i10045; + int i10046; + int i10047; + int i10048; + int i10049; + int i10050; + int i10051; + int i10052; + int i10053; + int i10054; + int i10055; + int i10056; + int i10057; + int i10058; + int i10059; + int i10060; + int i10061; + int i10062; + int i10063; + int i10064; + int i10065; + int i10066; + int i10067; + int i10068; + int i10069; + int i10070; + int i10071; + int i10072; + int i10073; + int i10074; + int i10075; + int i10076; + int i10077; + int i10078; + int i10079; + int i10080; + int i10081; + int i10082; + int i10083; + int i10084; + int i10085; + int i10086; + int i10087; + int i10088; + int i10089; + int i10090; + int i10091; + int i10092; + int i10093; + int i10094; + int i10095; + int i10096; + int i10097; + int i10098; + int i10099; + int i10100; + int i10101; + int i10102; + int i10103; + int i10104; + int i10105; + int i10106; + int i10107; + int i10108; + int i10109; + int i10110; + int i10111; + int i10112; + int i10113; + int i10114; + int i10115; + int i10116; + int i10117; + int i10118; + int i10119; + int i10120; + int i10121; + int i10122; + int i10123; + int i10124; + int i10125; + int i10126; + int i10127; + int i10128; + int i10129; + int i10130; + int i10131; + int i10132; + int i10133; + int i10134; + int i10135; + int i10136; + int i10137; + int i10138; + int i10139; + int i10140; + int i10141; + int i10142; + int i10143; + int i10144; + int i10145; + int i10146; + int i10147; + int i10148; + int i10149; + int i10150; + int i10151; + int i10152; + int i10153; + int i10154; + int i10155; + int i10156; + int i10157; + int i10158; + int i10159; + int i10160; + int i10161; + int i10162; + int i10163; + int i10164; + int i10165; + int i10166; + int i10167; + int i10168; + int i10169; + int i10170; + int i10171; + int i10172; + int i10173; + int i10174; + int i10175; + int i10176; + int i10177; + int i10178; + int i10179; + int i10180; + int i10181; + int i10182; + int i10183; + int i10184; + int i10185; + int i10186; + int i10187; + int i10188; + int i10189; + int i10190; + int i10191; + int i10192; + int i10193; + int i10194; + int i10195; + int i10196; + int i10197; + int i10198; + int i10199; + int i10200; + int i10201; + int i10202; + int i10203; + int i10204; + int i10205; + int i10206; + int i10207; + int i10208; + int i10209; + int i10210; + int i10211; + int i10212; + int i10213; + int i10214; + int i10215; + int i10216; + int i10217; + int i10218; + int i10219; + int i10220; + int i10221; + int i10222; + int i10223; + int i10224; + int i10225; + int i10226; + int i10227; + int i10228; + int i10229; + int i10230; + int i10231; + int i10232; + int i10233; + int i10234; + int i10235; + int i10236; + int i10237; + int i10238; + int i10239; + int i10240; + int i10241; + int i10242; + int i10243; + int i10244; + int i10245; + int i10246; + int i10247; + int i10248; + int i10249; + int i10250; + int i10251; + int i10252; + int i10253; + int i10254; + int i10255; + int i10256; + int i10257; + int i10258; + int i10259; + int i10260; + int i10261; + int i10262; + int i10263; + int i10264; + int i10265; + int i10266; + int i10267; + int i10268; + int i10269; + int i10270; + int i10271; + int i10272; + int i10273; + int i10274; + int i10275; + int i10276; + int i10277; + int i10278; + int i10279; + int i10280; + int i10281; + int i10282; + int i10283; + int i10284; + int i10285; + int i10286; + int i10287; + int i10288; + int i10289; + int i10290; + int i10291; + int i10292; + int i10293; + int i10294; + int i10295; + int i10296; + int i10297; + int i10298; + int i10299; + int i10300; + int i10301; + int i10302; + int i10303; + int i10304; + int i10305; + int i10306; + int i10307; + int i10308; + int i10309; + int i10310; + int i10311; + int i10312; + int i10313; + int i10314; + int i10315; + int i10316; + int i10317; + int i10318; + int i10319; + int i10320; + int i10321; + int i10322; + int i10323; + int i10324; + int i10325; + int i10326; + int i10327; + int i10328; + int i10329; + int i10330; + int i10331; + int i10332; + int i10333; + int i10334; + int i10335; + int i10336; + int i10337; + int i10338; + int i10339; + int i10340; + int i10341; + int i10342; + int i10343; + int i10344; + int i10345; + int i10346; + int i10347; + int i10348; + int i10349; + int i10350; + int i10351; + int i10352; + int i10353; + int i10354; + int i10355; + int i10356; + int i10357; + int i10358; + int i10359; + int i10360; + int i10361; + int i10362; + int i10363; + int i10364; + int i10365; + int i10366; + int i10367; + int i10368; + int i10369; + int i10370; + int i10371; + int i10372; + int i10373; + int i10374; + int i10375; + int i10376; + int i10377; + int i10378; + int i10379; + int i10380; + int i10381; + int i10382; + int i10383; + int i10384; + int i10385; + int i10386; + int i10387; + int i10388; + int i10389; + int i10390; + int i10391; + int i10392; + int i10393; + int i10394; + int i10395; + int i10396; + int i10397; + int i10398; + int i10399; + int i10400; + int i10401; + int i10402; + int i10403; + int i10404; + int i10405; + int i10406; + int i10407; + int i10408; + int i10409; + int i10410; + int i10411; + int i10412; + int i10413; + int i10414; + int i10415; + int i10416; + int i10417; + int i10418; + int i10419; + int i10420; + int i10421; + int i10422; + int i10423; + int i10424; + int i10425; + int i10426; + int i10427; + int i10428; + int i10429; + int i10430; + int i10431; + int i10432; + int i10433; + int i10434; + int i10435; + int i10436; + int i10437; + int i10438; + int i10439; + int i10440; + int i10441; + int i10442; + int i10443; + int i10444; + int i10445; + int i10446; + int i10447; + int i10448; + int i10449; + int i10450; + int i10451; + int i10452; + int i10453; + int i10454; + int i10455; + int i10456; + int i10457; + int i10458; + int i10459; + int i10460; + int i10461; + int i10462; + int i10463; + int i10464; + int i10465; + int i10466; + int i10467; + int i10468; + int i10469; + int i10470; + int i10471; + int i10472; + int i10473; + int i10474; + int i10475; + int i10476; + int i10477; + int i10478; + int i10479; + int i10480; + int i10481; + int i10482; + int i10483; + int i10484; + int i10485; + int i10486; + int i10487; + int i10488; + int i10489; + int i10490; + int i10491; + int i10492; + int i10493; + int i10494; + int i10495; + int i10496; + int i10497; + int i10498; + int i10499; + int i10500; + int i10501; + int i10502; + int i10503; + int i10504; + int i10505; + int i10506; + int i10507; + int i10508; + int i10509; + int i10510; + int i10511; + int i10512; + int i10513; + int i10514; + int i10515; + int i10516; + int i10517; + int i10518; + int i10519; + int i10520; + int i10521; + int i10522; + int i10523; + int i10524; + int i10525; + int i10526; + int i10527; + int i10528; + int i10529; + int i10530; + int i10531; + int i10532; + int i10533; + int i10534; + int i10535; + int i10536; + int i10537; + int i10538; + int i10539; + int i10540; + int i10541; + int i10542; + int i10543; + int i10544; + int i10545; + int i10546; + int i10547; + int i10548; + int i10549; + int i10550; + int i10551; + int i10552; + int i10553; + int i10554; + int i10555; + int i10556; + int i10557; + int i10558; + int i10559; + int i10560; + int i10561; + int i10562; + int i10563; + int i10564; + int i10565; + int i10566; + int i10567; + int i10568; + int i10569; + int i10570; + int i10571; + int i10572; + int i10573; + int i10574; + int i10575; + int i10576; + int i10577; + int i10578; + int i10579; + int i10580; + int i10581; + int i10582; + int i10583; + int i10584; + int i10585; + int i10586; + int i10587; + int i10588; + int i10589; + int i10590; + int i10591; + int i10592; + int i10593; + int i10594; + int i10595; + int i10596; + int i10597; + int i10598; + int i10599; + int i10600; + int i10601; + int i10602; + int i10603; + int i10604; + int i10605; + int i10606; + int i10607; + int i10608; + int i10609; + int i10610; + int i10611; + int i10612; + int i10613; + int i10614; + int i10615; + int i10616; + int i10617; + int i10618; + int i10619; + int i10620; + int i10621; + int i10622; + int i10623; + int i10624; + int i10625; + int i10626; + int i10627; + int i10628; + int i10629; + int i10630; + int i10631; + int i10632; + int i10633; + int i10634; + int i10635; + int i10636; + int i10637; + int i10638; + int i10639; + int i10640; + int i10641; + int i10642; + int i10643; + int i10644; + int i10645; + int i10646; + int i10647; + int i10648; + int i10649; + int i10650; + int i10651; + int i10652; + int i10653; + int i10654; + int i10655; + int i10656; + int i10657; + int i10658; + int i10659; + int i10660; + int i10661; + int i10662; + int i10663; + int i10664; + int i10665; + int i10666; + int i10667; + int i10668; + int i10669; + int i10670; + int i10671; + int i10672; + int i10673; + int i10674; + int i10675; + int i10676; + int i10677; + int i10678; + int i10679; + int i10680; + int i10681; + int i10682; + int i10683; + int i10684; + int i10685; + int i10686; + int i10687; + int i10688; + int i10689; + int i10690; + int i10691; + int i10692; + int i10693; + int i10694; + int i10695; + int i10696; + int i10697; + int i10698; + int i10699; + int i10700; + int i10701; + int i10702; + int i10703; + int i10704; + int i10705; + int i10706; + int i10707; + int i10708; + int i10709; + int i10710; + int i10711; + int i10712; + int i10713; + int i10714; + int i10715; + int i10716; + int i10717; + int i10718; + int i10719; + int i10720; + int i10721; + int i10722; + int i10723; + int i10724; + int i10725; + int i10726; + int i10727; + int i10728; + int i10729; + int i10730; + int i10731; + int i10732; + int i10733; + int i10734; + int i10735; + int i10736; + int i10737; + int i10738; + int i10739; + int i10740; + int i10741; + int i10742; + int i10743; + int i10744; + int i10745; + int i10746; + int i10747; + int i10748; + int i10749; + int i10750; + int i10751; + int i10752; + int i10753; + int i10754; + int i10755; + int i10756; + int i10757; + int i10758; + int i10759; + int i10760; + int i10761; + int i10762; + int i10763; + int i10764; + int i10765; + int i10766; + int i10767; + int i10768; + int i10769; + int i10770; + int i10771; + int i10772; + int i10773; + int i10774; + int i10775; + int i10776; + int i10777; + int i10778; + int i10779; + int i10780; + int i10781; + int i10782; + int i10783; + int i10784; + int i10785; + int i10786; + int i10787; + int i10788; + int i10789; + int i10790; + int i10791; + int i10792; + int i10793; + int i10794; + int i10795; + int i10796; + int i10797; + int i10798; + int i10799; + + if (unlikely) { + // Since Foo is not loaded this will turn into an uncommon trap + Class c = Foo.class; + + StringBuilder sb = new StringBuilder(); + } + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/gc/arguments/TestMaxHeapSizeTools.java --- a/test/gc/arguments/TestMaxHeapSizeTools.java Sun Nov 03 07:50:24 2013 +0000 +++ b/test/gc/arguments/TestMaxHeapSizeTools.java Tue Dec 03 14:13:06 2013 +0400 @@ -64,32 +64,29 @@ long newPlusOldSize = values[0] + values[1]; long smallValue = newPlusOldSize / 2; long largeValue = newPlusOldSize * 2; + long maxHeapSize = largeValue + (2 * 1024 * 1024); // -Xms is not set - checkErgonomics(new String[] { gcflag, "-Xmx16M" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1); // -Xms is set to zero - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1); // -Xms is set to small value - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1); // -Xms is set to large value - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue }, values, largeValue, largeValue); - // the next case has already been checked elsewhere and gives an error - // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - // the next case has already been checked elsewhere too - // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, values[0], largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1); } private static long align_up(long value, long alignment) { diff -r c31f0cbe6d9e -r 0611ce949aaa test/gc/arguments/TestMaxNewSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestMaxNewSize.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,122 @@ +/* +* 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. +*/ + +/* + * @test TestMaxNewSize + * @key gc + * @bug 7057939 + * @summary Make sure that MaxNewSize always has a useful value after argument + * processing. + * @library /testlibrary + * @build TestMaxNewSize + * @run main TestMaxNewSize -XX:+UseSerialGC + * @run main TestMaxNewSize -XX:+UseParallelGC + * @run main TestMaxNewSize -XX:+UseConcMarkSweepGC + * @run main TestMaxNewSize -XX:+UseG1GC + * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import java.math.BigInteger; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.oracle.java.testlibrary.*; + +public class TestMaxNewSize { + + private static void checkMaxNewSize(String[] flags, int heapsize) throws Exception { + BigInteger actual = new BigInteger(getMaxNewSize(flags)); + System.out.println(actual); + if (actual.compareTo(new BigInteger((new Long(heapsize)).toString())) == 1) { + throw new RuntimeException("MaxNewSize value set to \"" + actual + + "\", expected otherwise when running with the following flags: " + Arrays.asList(flags).toString()); + } + } + + private static void checkIncompatibleNewSize(String[] flags) throws Exception { + ArrayList finalargs = new ArrayList(); + finalargs.addAll(Arrays.asList(flags)); + finalargs.add("-version"); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Initial young gen size set larger than the maximum young gen size"); + } + + private static boolean isRunningG1(String[] args) { + for (int i = 0; i < args.length; i++) { + if (args[i].contains("+UseG1GC")) { + return true; + } + } + return false; + } + + private static String getMaxNewSize(String[] flags) throws Exception { + ArrayList finalargs = new ArrayList(); + finalargs.addAll(Arrays.asList(flags)); + if (isRunningG1(flags)) { + finalargs.add("-XX:G1HeapRegionSize=1M"); + } + finalargs.add("-XX:+PrintFlagsFinal"); + finalargs.add("-version"); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + String stdout = output.getStdout(); + //System.out.println(stdout); + return getFlagValue("MaxNewSize", stdout); + } + + private static String getFlagValue(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + String match = m.group(); + return match.substring(match.lastIndexOf(" ") + 1, match.length()); + } + + public static void main(String args[]) throws Exception { + String gcName = args[0]; + final int M32 = 32 * 1024 * 1024; + final int M64 = 64 * 1024 * 1024; + final int M96 = 96 * 1024 * 1024; + final int M128 = 128 * 1024 * 1024; + checkMaxNewSize(new String[] { gcName, "-Xmx128M" }, M128); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=5" }, M128); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M" }, M128); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:OldSize=96M" }, M128); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:MaxNewSize=32M" }, M32); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M", "-XX:MaxNewSize=32M" }, M32); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=6", "-XX:MaxNewSize=32M" }, M32); + checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-Xms96M" }, M128); + checkMaxNewSize(new String[] { gcName, "-Xmx96M", "-Xms96M" }, M96); + checkMaxNewSize(new String[] { gcName, "-XX:NewSize=128M", "-XX:MaxNewSize=50M"}, M128); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/gc/g1/TestHumongousCodeCacheRoots.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestHumongousCodeCacheRoots.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,143 @@ +/* + * 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. + */ + +/* + * @test + * @key regression + * @key gc + * @bug 8027756 + * @library /testlibrary /testlibrary/whitebox + * @build TestHumongousCodeCacheRoots + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @summary Humongous objects may have references from the code cache + * @run main TestHumongousCodeCacheRoots +*/ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +import java.util.ArrayList; +import java.util.Arrays; + +class TestHumongousCodeCacheRootsHelper { + + static final int n = 1000000; + static final int[] AA = new int[n]; + static final int[] BB = new int[n]; + + public static void main(String args[]) throws Exception { + // do some work so that the compiler compiles this method, inlining the + // reference to the integer array (which is a humonguous object) into + // the code cache. + for(int i = 0; i < n; i++) { + AA[i] = 0; + BB[i] = 0; + } + // trigger a GC that checks that the verification code allows humongous + // objects with code cache roots; objects should be all live here. + System.gc(); + + // deoptimize everyhing: this should make all compiled code zombies. + WhiteBox wb = WhiteBox.getWhiteBox(); + wb.deoptimizeAll(); + + // trigger a GC that checks that the verification code allows humongous + // objects with code cache roots; objects should be all live here. + System.gc(); + + // wait a little for the code cache sweeper to try to clean up zombie nmethods + // and unregister the code roots. + try { Thread.sleep(5000); } catch (InterruptedException ex) { } + + // do some work on the arrays to make sure that they need to be live after the GCs + for(int i = 0; i < n; i++) { + AA[i] = 1; + BB[i] = 10; + } + + System.out.println(); + } +} + +public class TestHumongousCodeCacheRoots { + + /** + * Executes a class in a new VM process with the given parameters. + * @param vmargs Arguments to the VM to run + * @param classname Name of the class to run + * @param arguments Arguments to the class + * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string + * @return The OutputAnalyzer with the results for the invocation. + */ + public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception { + ArrayList finalargs = new ArrayList(); + + String[] whiteboxOpts = new String[] { + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", System.getProperty("java.class.path"), + }; + + if (useTestDotJavaDotOpts) { + // System.getProperty("test.java.opts") is '' if no options is set, + // we need to skip such a result + String[] externalVMOpts = new String[0]; + if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { + externalVMOpts = System.getProperty("test.java.opts").split(" "); + } + finalargs.addAll(Arrays.asList(externalVMOpts)); + } + + finalargs.addAll(Arrays.asList(vmargs)); + finalargs.addAll(Arrays.asList(whiteboxOpts)); + finalargs.add(classname); + finalargs.addAll(Arrays.asList(arguments)); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + return output; + } + + public static void runTest(String compiler, String[] other) throws Exception { + ArrayList joined = new ArrayList(); + joined.add(compiler); + joined.addAll(Arrays.asList(other)); + runWhiteBoxTest(joined.toArray(new String[0]), TestHumongousCodeCacheRootsHelper.class.getName(), + new String[] {}, false); + } + + public static void main(String[] args) throws Exception { + final String[] baseArguments = new String[] { + "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1M", "-Xmx100M", // make sure we get a humongous region + "-XX:+UnlockDiagnosticVMOptions", + "-XX:InitiatingHeapOccupancyPercent=1", // strong code root marking + "-XX:+G1VerifyHeapRegionCodeRoots", "-XX:+VerifyAfterGC", // make sure that verification is run + "-XX:NmethodSweepFraction=1", "-XX:NmethodSweepCheckInterval=1", // make the code cache sweep more predictable + }; + runTest("-client", baseArguments); + runTest("-server", baseArguments); + } +} + diff -r c31f0cbe6d9e -r 0611ce949aaa test/gc/startup_warnings/TestCMSForegroundFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMSForegroundFlags.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,52 @@ +/* +* 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. +*/ + +/* +* @test TestCMSForegroundFlags +* @key gc +* @bug 8027132 +* @summary Test that the deprecated CMS foreground collector flags print warning messages +* @library /testlibrary +* @run main TestCMSForegroundFlags -XX:-UseCMSCompactAtFullCollection UseCMSCompactAtFullCollection +* @run main TestCMSForegroundFlags -XX:CMSFullGCsBeforeCompaction=4 CMSFullGCsBeforeCompaction +* @run main TestCMSForegroundFlags -XX:-UseCMSCollectionPassing UseCMSCollectionPassing +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestCMSForegroundFlags { + public static void main(String[] args) throws Exception { + if (args.length != 2) { + throw new Exception("Expected two arguments,flagValue and flagName"); + } + String flagValue = args[0]; + String flagName = args[1]; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flagValue, "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: " + flagName + " is deprecated and will likely be removed in a future release."); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/runtime/CompressedOops/CompressedClassPointers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CompressedOops/CompressedClassPointers.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,136 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8024927 + * @summary Testing address of compressed class pointer space as best as possible. + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CompressedClassPointers { + + public static void smallHeapTest() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedBaseAddress=8g", + "-Xmx128m", + "-XX:+PrintCompressedOopsMode", + "-XX:+VerifyBeforeGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Narrow klass base: 0x0000000000000000"); + output.shouldHaveExitValue(0); + } + + public static void smallHeapTestWith3G() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:CompressedClassSpaceSize=3g", + "-Xmx128m", + "-XX:+PrintCompressedOopsMode", + "-XX:+VerifyBeforeGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Narrow klass base: 0x0000000000000000, Narrow klass shift: 3"); + output.shouldHaveExitValue(0); + } + + public static void largeHeapTest() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx30g", + "-XX:+PrintCompressedOopsMode", + "-XX:+VerifyBeforeGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Narrow klass base: 0x0000000000000000"); + output.shouldContain("Narrow klass shift: 0"); + output.shouldHaveExitValue(0); + } + + public static void largePagesTest() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-Xmx128m", + "-XX:+UseLargePages", + "-XX:+PrintCompressedOopsMode", + "-XX:+VerifyBeforeGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Narrow klass base:"); + output.shouldHaveExitValue(0); + } + + public static void sharingTest() throws Exception { + // Test small heaps + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./sample.jsa", + "-Xmx128m", + "-XX:SharedBaseAddress=8g", + "-XX:+PrintCompressedOopsMode", + "-XX:+VerifyBeforeGC", + "-Xshare:dump"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./sample.jsa", + "-Xmx128m", + "-XX:SharedBaseAddress=8g", + "-XX:+PrintCompressedOopsMode", + "-Xshare:on", + "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("sharing"); + output.shouldHaveExitValue(0); + + } catch (RuntimeException e) { + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } + + 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(); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/runtime/memory/ReadFromNoaccessArea.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/ReadFromNoaccessArea.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/* + * @test + * @summary Test that touching noaccess area in class ReservedHeapSpace results in SIGSEGV/ACCESS_VIOLATION + * @library /testlibrary /testlibrary/whitebox + * @build ReadFromNoaccessArea + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main ReadFromNoaccessArea + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ReadFromNoaccessArea { + + public static void main(String args[]) throws Exception { + if (!Platform.is64bit()) { + System.out.println("ReadFromNoaccessArea tests is useful only on 64bit architecture. Passing silently."); + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:+UseCompressedOops", + "-XX:HeapBaseMinAddress=33G", + DummyClassWithMainTryingToReadFromNoaccessArea.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + System.out.println("******* Printing stdout for analysis in case of failure *******"); + System.out.println(output.getStdout()); + System.out.println("******* Printing stderr for analysis in case of failure *******"); + System.out.println(output.getStderr()); + System.out.println("***************************************************************"); + if (output.getStdout() != null && output.getStdout().contains("WB_ReadFromNoaccessArea method is useless")) { + // Test conditions broken. There is no protected page in ReservedHeapSpace in these circumstances. Silently passing test. + return; + } + if (Platform.isWindows()) { + output.shouldContain("EXCEPTION_ACCESS_VIOLATION"); + } else if (Platform.isOSX()) { + output.shouldContain("SIGBUS"); + } else { + output.shouldContain("SIGSEGV"); + } + } + + public static class DummyClassWithMainTryingToReadFromNoaccessArea { + + // This method calls whitebox method reading from noaccess area + public static void main(String args[]) throws Exception { + WhiteBox.getWhiteBox().readFromNoaccessArea(); + throw new Exception("Call of readFromNoaccessArea succeeded! This is wrong. Crash expected. Test failed."); + } + } + +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/runtime/memory/RunUnitTestsConcurrently.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/RunUnitTestsConcurrently.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/* + * @test + * @summary Test launches unit tests inside vm concurrently + * @library /testlibrary /testlibrary/whitebox + * @build RunUnitTestsConcurrently + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI RunUnitTestsConcurrently 30 15000 + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class RunUnitTestsConcurrently { + + private static WhiteBox wb; + private static long timeout; + private static long timeStamp; + + public static class Worker implements Runnable { + @Override + public void run() { + while (System.currentTimeMillis() - timeStamp < timeout) { + WhiteBox.getWhiteBox().runMemoryUnitTests(); + } + } + } + + public static void main(String[] args) throws InterruptedException { + if (!Platform.isDebugBuild() || !Platform.is64bit()) { + return; + } + wb = WhiteBox.getWhiteBox(); + System.out.println("Starting threads"); + + int threads = Integer.valueOf(args[0]); + timeout = Long.valueOf(args[1]); + + timeStamp = System.currentTimeMillis(); + + Thread[] threadsArray = new Thread[threads]; + for (int i = 0; i < threads; i++) { + threadsArray[i] = new Thread(new Worker()); + threadsArray[i].start(); + } + for (int i = 0; i < threads; i++) { + threadsArray[i].join(); + } + + System.out.println("Quitting test."); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/runtime/memory/StressVirtualSpaceResize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/StressVirtualSpaceResize.java Tue Dec 03 14:13:06 2013 +0400 @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/* + * @test + * @summary Stress test that expands/shrinks VirtualSpace + * @library /testlibrary /testlibrary/whitebox + * @build StressVirtualSpaceResize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI StressVirtualSpaceResize + */ + +import sun.hotspot.WhiteBox; + +public class StressVirtualSpaceResize { + + public static void main(String args[]) throws Exception { + if (WhiteBox.getWhiteBox().stressVirtualSpaceResize(1000, 0xffffL, 0xffffL) != 0) + throw new RuntimeException("Whitebox method stressVirtualSpaceResize returned non zero exit code"); + } +} diff -r c31f0cbe6d9e -r 0611ce949aaa test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Sun Nov 03 07:50:24 2013 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Dec 03 14:13:06 2013 +0400 @@ -144,4 +144,10 @@ // force Full GC public native void fullGC(); + + // Tests on ReservedSpace/VirtualSpace classes + public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations); + public native void runMemoryUnitTests(); + public native void readFromNoaccessArea(); + }